Ver código fonte

Reorganized the TripalField class and removed the attach_info() function. Broke out into two new functions: create_info and create_instance_info. This is better as it doesn't try to lump creating of a field and creating of an instance into one function and it supports all of thesettings for both operations

Stephen Ficklin 9 anos atrás
pai
commit
76681a2520
28 arquivos alterados com 2632 adições e 1646 exclusões
  1. 43 194
      tripal/api/tripal.entities.api.inc
  2. 238 22
      tripal/includes/TripalField.inc
  3. 57 0
      tripal/includes/tripal.fields.inc
  4. 20 43
      tripal/tripal.module
  5. 1 1
      tripal_chado/api/tripal_chado.api.inc
  6. 68 24
      tripal_chado/includes/fields/chado_base__dbxref_id.inc
  7. 82 32
      tripal_chado/includes/fields/chado_base__organism_id.inc
  8. 77 25
      tripal_chado/includes/fields/chado_feature__md5checksum.inc
  9. 72 55
      tripal_chado/includes/fields/chado_feature__residues.inc
  10. 77 28
      tripal_chado/includes/fields/chado_feature__seqlen.inc
  11. 68 24
      tripal_chado/includes/fields/chado_gene__transcripts.inc
  12. 91 40
      tripal_chado/includes/fields/chado_linker__contact.inc
  13. 21 4
      tripal_chado/includes/fields/chado_linker__cvterm.inc
  14. 116 49
      tripal_chado/includes/fields/chado_linker__cvterm_adder.inc
  15. 78 33
      tripal_chado/includes/fields/chado_linker__dbxref.inc
  16. 97 54
      tripal_chado/includes/fields/chado_linker__expression.inc
  17. 67 23
      tripal_chado/includes/fields/chado_linker__featureloc.inc
  18. 68 22
      tripal_chado/includes/fields/chado_linker__genotype.inc
  19. 69 22
      tripal_chado/includes/fields/chado_linker__phenotype.inc
  20. 264 283
      tripal_chado/includes/fields/chado_linker__prop.inc
  21. 122 44
      tripal_chado/includes/fields/chado_linker__prop_adder.inc
  22. 71 23
      tripal_chado/includes/fields/chado_linker__pub.inc
  23. 77 27
      tripal_chado/includes/fields/chado_linker__relationship.inc
  24. 69 22
      tripal_chado/includes/fields/chado_linker__synonym.inc
  25. 74 27
      tripal_chado/includes/fields/chado_organism__type_id.inc
  26. 0 4
      tripal_chado/includes/tripal_chado.field_storage.inc
  27. 534 518
      tripal_chado/includes/tripal_chado.fields.inc
  28. 11 3
      tripal_chado/includes/tripal_chado.setup.inc

+ 43 - 194
tripal/api/tripal.entities.api.inc

@@ -174,8 +174,49 @@ function tripal_create_bundle($vocabulary, $accession, $term_name, &$error = '')
   // Get the bundle object.
   $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
 
-  // Allow modules now add fields to the bundle
-  module_invoke_all('add_bundle_fields', 'TripalEntity', $bundle, $term);
+  // Get the list of fields to create.
+  foreach (module_implements('field_create_info') as $module) {
+    $function = $module . '_field_create_info';
+    if (function_exists($function)) {
+      $fields = $function('TripalEntity', $bundle, $term);
+      if (!$fields){
+        continue;
+      }
+      foreach ($fields as $field_name => $info) {
+        // If the field already exists then skip it.
+        $field = field_info_field($info['field_name']);
+        if ($field) {
+          continue;
+        }
+        $field = field_create_field($info);
+        if (!$field) {
+          tripal_set_message(t("Could not create new field: %field.",
+            array('%field' =>  $info['field_name'])), TRIPAL_ERROR);
+        }
+      }
+    }
+  }
+
+  // Now get the list of field instances to add to the bundle.
+  foreach (module_implements('field_create_instance_info') as $module) {
+    $function = $module . '_field_create_instance_info';
+    if (function_exists($function)) {
+      $fields = $function('TripalEntity', $bundle, $term);
+      if (!$fields){
+        continue;
+      }
+      foreach ($fields as $field_name => $info) {
+        // If the field is already attached to this bundle then skip it.
+        $field = field_info_field($info['field_name']);
+        if ($field and array_key_exists('bundles', $field) and
+            array_key_exists('TripalEntity', $field['bundles']) and
+            in_array($bundle_name, $field['bundles']['TripalEntity'])) {
+          continue;
+        }
+        $instance = field_create_instance($info);
+      }
+    }
+  }
 
   return TRUE;
 }
@@ -203,91 +244,6 @@ function tripal_refresh_bundle_fields($bundle_name) {
   module_invoke_all('update_bundle_fields', 'TripalEntity', $bundle, $term);
 }
 
-
-/**
- * Adds a new field and attaches it to a bundle
- *
- * @param $field_name
- *   The name of the field.
- * @param $field_info
- *   An associative array containing the field information.  The following
- *   key/value pairs are supported:
- *     'field_type' : a valid field type.  May be any of the Drupal default
- *       fields, one created by the tripal_chado module or another custom module.
- *     'widget_type' : a valid widget type. May be any of the Drupal default
- *       fields, one created by the tripal_chado module or another custom module.
- *     'field_settings' : an array of settings that are appropriate for the
- *       selected field type.
- *     'widget_settings' : an array of settings that are appropriate for the
- *       selected widget type.
- *     'description' :  a default description for this field.
- *     'label' : a label used as a header for this field.
- *     'is_required' : indicates if the field is required in the edit form.
- *     'cardinality' : indicates the number of values this field can support.
- *       the default is 1 (meaning only one value). Use a value of
- *       FIELD_CARDINALITY_UNLIMITED for unlimited number of values.
- *     'default_value' : A default value for the field.
- *     'format' : A string indicating the format for the field. Must be
- *       specific to the field.
- * @param $entity_type_name
- *   The entity type name.
- * @param $bundle_name
- *   The bundle name.
- *
- * TODO: this function really shouldn't try to create an instance and
- * attach to a bundle  at the same time.
- */
-function tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name) {
-
-  $field = field_info_field($field_name);
-
-  // If the field exists and is attached to this bundle then just return,
-  // there is nothing left to do.
-  if ($field and array_key_exists('bundles', $field) and
-      array_key_exists($entity_type_name, $field['bundles']) and
-      in_array($bundle_name, $field['bundles'][$entity_type_name])) {
-    return;
-  }
-
-  $cardinality = 1;
-  if (array_key_exists('cardinality', $field_info) and is_numeric($field_info['cardinality'])) {
-    $cardinality = $field_info['cardinality'];
-  }
-
-  // If the field doesn't exist then create it.
-  if (!$field) {
-    $field = array(
-      'field_name' => $field_name,
-      'type' => $field_info['field_type'],
-      'cardinality' => $cardinality,
-      'locked' => FALSE,
-      'storage' => array(
-        'type' => $field_info['storage']
-      ),
-      'settings' => $field_info['field_settings'],
-    );
-    field_create_field($field);
-  }
-
-  // Attach the field to the bundle.
-  $field_instance = array(
-    'field_name' => $field_name,
-    'label' => $field_info['label'],
-    'description' => $field_info['description'],
-    'widget' => array(
-      'type' => $field_info['widget_type'],
-      'settings' => $field_info['widget_settings'],
-    ),
-    'entity_type' => $entity_type_name,
-    'required' => $field_info['is_required'],
-    'settings' => $field_info['field_settings'],
-    'bundle' => $bundle_name,
-    'default_value' => array_key_exists('default_value', $field_info) ? $field_info['default_value'] : '',
-    'format' => array_key_exists('format', $field_info) ? $field_info['format'] : '',
-  );
-  field_create_instance($field_instance);
-}
-
 /**
  * Updates an existing field and its attached instance to a bundle.
  *
@@ -400,113 +356,6 @@ function hook_entity_create(&$entity, $entity_type) {
 }
 
 
-/**
- * Adds fields to a bundle type.
- *
- * When a new bundle (Tripal content type) is created, the tripal module
- * allows any other module the implements this hook to add fields too it. This
- * hook is called automatically.
- *
- * @param $entity_type
- *   The type of entity (e.g. 'TripalEntity')
- * @param $bundle
- *   An instance of a TripalBundle object.  This is the bundle to which
- *   the fields will be added.
- * @param $term
- *   An instance of a TripalTerm object. Each TripalBundle is associated with
- *   a controlled vocabulary term. This is the term object for the bundle.
- *
- * @return
- *   There is no return value.
- */
-function hook_add_bundle_fields($entity_type, $bundle, $term) {
-
-  //
-  // The example code below is derived from the tripal_chado modules and
-  // adds a 'synonym' field to the bundle.
-  //
-
-  $bundle_name = $bundle->name;
-
-  // This array will hold details that map the bundle to tables in Chado.
-  $bundle_data = array();
-
-  // Get the cvterm that corresponds to this TripalTerm object.
-  $vocab = entity_load('TripalVocab', array($term->vocab_id));
-  $vocab = reset($vocab);
-  $match = array(
-    'dbxref_id' => array(
-      'db_id' => array(
-        'name' => $vocab->vocabulary,
-      ),
-      'accession' => $term->accession
-    ),
-  );
-  $cvterm = chado_generate_var('cvterm', $match);
-
-
-  // Get the default table that this term maps to.
-  $default = db_select('tripal_cv_defaults', 't')
-  ->fields('t')
-  ->condition('cv_id', $cvterm->cv_id->cv_id)
-  ->execute()
-  ->fetchObject();
-  if ($default) {
-    $bundle_data = array(
-      'cv_id' => $cvterm->cv_id->cv_id,
-      'cvterm_id' => $cvterm->cvterm_id,
-      'data_table' => $default->table_name,
-      'type_table' => $default->table_name,
-      'field' =>  $default->field_name,
-    );
-  }
-  else {
-    return;
-  }
-
-  // Formulate the name of the synonym table.
-  $syn_table = $bundle_data['data_table'] . '_synonym';
-
-  // Don't add a field to this bundle if
-  if (!chado_table_exists($syn_table)) {
-    return;
-  }
-
-  $field_name = $syn_table;
-  $schema = chado_get_schema($syn_table);
-  $pkey = $schema['primary key'][0];
-
-  // The Tripal Chado module needs to know what Chado table and field
-  // this field maps to, as well as the base table that it maps to
-  // if this field will map to a record in a linking table.
-  $field_settings = array(
-    // The Chado table that this field maps to.
-    'chado_table' => $syn_table,
-    // The column in the chado table that this field maps to.
-    'chado_column' => $pkey,
-    // The base table that this field is connected to.
-    'base_table' => $base_table,
-    'semantic_web' => '',
-  );
-
-  // Finally set the field values.
-  $field_info = array(
-    'field_type' => 'synonym',
-    'widget_type' => 'tripal_fields_synonym_widget',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Synonyms',
-    'is_required' => 0,
-    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-    'storage' => 'field_chado_storage',
-    'field_settings' => $field_settings,
-  );
-
-  // Call the Tripal API function tripal_add_bundle_field to complete the
-  // addition of the field to the bundle.
-  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
-}
-
 /**
  * @section
  * Bundle Variables.

+ 238 - 22
tripal/includes/TripalField.inc

@@ -2,30 +2,79 @@
 
 
 /**
- * A base class for all Fields supported by Tripal.
+ * A base class for all fields supported by Tripal.
  *
- * This class provides all of the necessary functions for a TripalField field.
- * It helps simplify and unify the process of creating fields for Tripal.  This
- * class simply defines the function prototypes. It is up to the class that
- * extends this class to implement the functions.
+ * The Field API of Drupal defines three "levels" for fields:  field types,
+ * fields, and instances of fields.  All fields must be of a specific type, and
+ * the field types are typically defined using the hook_field_info() hook.
+ * Normally, using Drupal's Field API, fields can be created by using the
+ * field_create_field() function which defines the parameters and settings
+ * for the field.  The field_create_instance() function is then used to attach
+ * a field to a bundle and to set local parameters and settings for the field
+ * when attached to the bundle.  There are also a variety of hooks for creating
+ * widgets, formatters, customizaing settings forms, loading values, validating
+ * widget forms, etc. Rather than use all of these hooks, the TripalField class
+ * is used to consolidate and simplify creation and management of Fields.
  *
- * Each module that creates new fields should use the normal Field API hooks
- * (e.g. hook_field_info(), hook_field_widget_form(), etc.) to instantiate the
- * appropriate TripalField class.
+ * A module can extend this class to create new fields, and attach them to
+ * bundles.  The class is structure to allow fields to attach themselves to
+ * bundles. This is a bit different from how fields would normally be
+ * attached. But allows a field to be self-aware and all of the functionality
+ * for a field is self-contained in the Class implementation.  To change
+ * functionality a developer need only edit the class file for a field rathaer
+ * than look for all of the Field API hook that would typically be spread
+ * around the module.
  *
- * Because of the way Drupal handles callbacks, AJAX callbacks, and theme
- * functions cannot be part of the implementation of this class.  Those
- * functions if needed, should be added to the bottom of the file where the
- * child class is housed.
+ * This field also supports use of controlled vocabulaaries for providing
+ * "types" to these fields. This is important for use with the semantic web
+ * support for Tripal v3.
+ *
+ * AJAX callbacks, and theme functions unfortunately cannot be part of the
+ * implementation of this class.  To keep all functionality for a field
+ * in the same file, it is recommended that those functions, if needed, should
+ * be added to the bottom of the file where the child class is housed, and each
+ * TripalField child class should each be written in a separate file.
  *
  */
 class TripalField {
   /**
-   * Provides information about this field.
+   * Define this field type.
    *
-   * @return array
-   *   An associative array with key/value pairs compatible with those from
-   *   the hook_field_info() function of the Drupal Field API.
+   * @return
+   * An array whose keys are field type names and whose values are arrays
+   * describing the field type. The keys are the same as for the
+   * hook_field_info() function, which are:
+   *   - label: The human-readable name of the field type.
+   *   - description: A short description for the field type.
+   *   - settings: An array whose keys are the names of the settings available
+   *     for the field type, and whose values are the default values for those
+   *     settings.
+   *   - instance_settings: An array whose keys are the names of the settings
+   *     available for instances of the field type, and whose values are the
+   *     default values for those settings. Instance-level settings can have
+   *     different values on each field instance, and thus allow greater
+   *     flexibility than field-level settings. It is recommended to put
+   *     settings at the instance level whenever possible. Notable
+   *     exceptions: settings acting on the schema definition, or settings
+   *     that Views needs to use across field instances (for example, the
+   *     list of allowed values).
+   *   - default_widget: The machine name of the default widget to be used by
+   *     instances of this field type, when no widget is specified in the
+   *     instance definition. This widget must be available whenever the field
+   *     type is available (i.e. provided by the field type module, or by a
+   *     module the field type module depends on).  Valid names are those
+   *     provided by the widget_info() function of this class.
+   *   - default_formatter: The machine name of the default formatter to be
+   *     used by instances of this field type, when no formatter is specified
+   *     in the instance definition. This formatter must be available whenever
+   *     the field type is available (i.e. provided by the field type module,
+   *     or by a module the field type module depends on).  Valid names are
+   *     those provided by the formater_info() function of this class.
+   *   - no_ui: (optional) A boolean specifying that users should not be allowed
+   *     to create fields and instances of this field type through the UI.
+   *     Such fields can only be created programmatically with
+   *     field_create_field() and field_create_instance(). Defaults to
+   *     FALSE.
    */
   public function field_info() {
     return array(
@@ -34,20 +83,187 @@ class TripalField {
 
 
   /**
-   * Provides an array that allows Tripal to attach a field to an entity.
+   * Provides the information required for creating a field.
+   *
+   * These settings are global for every instance of the field.
+   *
+   * he TripalField class allows a field to decide which bundles it would
+   * like to attach itself to. Therefore, the entity type, and bundle are
+   * passed as arguments to allow the field to decide if it wants to be
+   * attached.
+   *
+   * @param $entity_type
+   *   The class name for the entity type (e.g. TripalEntity).
+   * @param TripalBundle $bundle
+   *   The TripalBundle object.  This is the bundle that is being offered
+   *   to the field for attachement. The function will determine if this
+   *   field should be attached to this bundle.
+   * @param $details
+   * @return
+   *   A field definition array. The return value is identical to that
+   *   provided to the field_create_info() function. The field_name and
+   *   type properties are required. The semantic_web value is also required
+   *   under the settings. Other properties, if omitted, will be
+   *   given the following default values:
+   *     - cardinality: 1
+   *     - locked: FALSE. Set to TRUE if you do not want your field to be
+   *       re-used or deleted.
+   *     - settings: each omitted setting is given the default value
+   *       defined in field_info().
+   *       - semantic_web: a controlled vocabulary term written in the form
+   *         [CV short name]:[accession] (e.g. SO:000745).
+   *     - storage:
+   *       - type: the storage backend specified in the 'field_storage_default'
+   *         system variable.
+   *       - settings: each omitted setting is given the default value specified
+   *         in hook_field_storage_info().
+   *
+   *  Nothing is returned when this field will not be attached to the bundle.
+   */
+  public function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+  }
+
+  /**
+   * Provides the information required for creating an instance of a field.
+   *
+   * A field instance is a field that has been created using the values provided
+   * by the create_info() function of this class, and which is attached to
+   * a bundle.
+   *
+   * The TripalField class allows a field to decide which bundles it would
+   * like to attach itself to. Therefore, the entity type, and bundle are
+   * passed as arguments to allow the field to decide if it wants to be
+   * attached and if so then this function will provide the details to create
+   * the field.  The field instance can later be attached to the bundle
+   * using information provided by the create_instance_info() function.
+   *
+   * @param $entity_type
+   *   The entity type Class to which the bundle belongs.
+   * @param $bundle.
+   *   An instance of a TripalBundle object.  This is the bundle to which
+   *   the field can be added.
+   * @param $details
+   *   An associative array containing additional details provided by the
+   *   calling module that can be used by the function to determine if the
+   *   bundle should be attached to.
    *
-   * @todo: This function needs better documentation.
+   * @return
+   *  A field instance definition array. The values of thie array are identical
+   *  to those passed to the field_create_instance() function. The field_name,
+   *  entity_type and bundle (name of the bundle) properties are required.
+   *  Other properties, if omitted, will be given the following default values:
+   *    - label: the field name
+   *    - description: empty string
+   *    - required: FALSE
+   *    - default_value_function: empty string
+   *    - settings: each omitted setting is given the default value specified
+   *      in hook_field_info().
+   *    - widget:
+   *      - type: the default widget specified in field_info().
+   *      - settings: each omitted setting is given the default value specified
+   *        in widget_info().
+   *    - display: An instance can support multiple view modes. Eeach mode must
+   *      be listed as a separate key (e.g. 'default') with a the following
+   *      values (and their default specified below.  If display is not
+   *      included then the settings for the 'default' view mode will be added
+   *      automatically, and each view mode in the definition will be completed
+   *      with the following default values:
+   *      - label: 'above'
+   *      - type: the default formatter specified in field_info().
+   *      - settings: each omitted setting is given the default value specified
+   *        in formatter_info().
+   *      View modes not present in the definition are left empty, and the
+   *      field will not be displayed in this mode.
+   *
+   *  Nothing is returned when this field will not be attached to the bundle.
+   */
+  public function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+  }
+
+
+
+  /**
+   * A helper function to determine if this field wants to attach to a bundle.
+   *
+   * Because the create_info() and create_instance_info() functions both need
+   * to determine if they should attach to a bundle, this function is provided
+   * as a helper function to perform that check.  Any class that extends the
+   * TripalField class can use this function provide a single function that
+   * both create_info() and create_instance_info() can use.
+   *
+   * @param $entity_type
+   *   The entity type Class to which the bundle belongs.
+   * @param $bundle.
+   *   An instance of a TripalBundle object.  This is the bundle to which
+   *   the field can be added.
+   * @param $details
+   *   An associative array containing additional details provided by the
+   *   calling module that can be used by the function to determine if the
+   *   bundle should be attached to.
    *
+   * @return
+   *   TRUE if the field should attach to the bundle. FALSE if not.
    */
+  protected function can_attach($entity_type, $bundle, $details) {
+
+  }
+
   public function attach_info($entity_type, $bundle, $settings) {
 
   }
+
   /**
-   * Provides information about the widget for this field.
+   *  Provides information about the widgets provided by this field.
    *
-   * @return array
-   *   An associative array with key/value paris compatible with those from the
-   *   hook_field_widget_info() function of the Drupal Field API.
+   *  This function returns an array describing the widget types implemented by
+   *  the field.  The widgets created by this field are expecte to be used only
+   *  by this field.
+   *
+   * @param $entity_type
+   *   The entity type Class to which the bundle belongs.
+   * @param $bundle.
+   *   An instance of a TripalBundle object.  This is the bundle to which
+   *   the field can be added.
+   * @param $details
+   *   An associative array containing additional details provided by the
+   *   calling module that can be used by the function to determine if the
+   *   bundle should be attached to.
+   *
+   * @return
+   *   An associative array where the keys are widget type names. To avoid
+   *   name clashes, widget type names should be prefixed with the name of
+   *   the module that exposes them. The values are arrays describing the
+   *   widget type, with the following key/value pairs:
+   *
+   *     - label: The human-readable name of the widget type.
+   *     - description: A short description for the widget type.
+   *     - field types: An array of field types the widget supports.
+   *     - settings: An array whose keys are the names of the settings
+   *       available for the widget type, and whose values are the default
+   *       values for those settings.
+   *     - behaviors: (optional) An array describing behaviors of the widget,
+   *       with the following elements:
+   *       - multiple values: One of the following constants:
+   *          - FIELD_BEHAVIOR_DEFAULT: (default) If the widget allows the
+   *            input of one single field value (most common case). The widget
+   *            will be repeated for each value input.
+   *          - FIELD_BEHAVIOR_CUSTOM: If one single copy of the widget can
+   *            receive several field values. Examples: checkboxes, multiple
+   *            select, comma-separated textfield.
+   *        - default value: One of the following constants:
+   *          - FIELD_BEHAVIOR_DEFAULT: (default) If the widget accepts
+   *            default values.
+   *          - FIELD_BEHAVIOR_NONE: if the widget does not support
+   *            default values.
+   *     - weight: (optional) An integer to determine the weight of this
+   *       widget relative to other widgets in the Field UI when selecting a
+   *       widget for a given field instance.
    */
   public function widget_info() {
     return array(

+ 57 - 0
tripal/includes/tripal.fields.inc

@@ -43,6 +43,63 @@ function tripal_field_formatter_info() {
     ),
   );
 }
+
+/**
+ * Implements hook_create_info().
+ *
+ * This is a Tripal defined hook that supports integration with the
+ * TripalEntity field.
+ */
+function tripal_field_create_info($entity_type, $bundle, $term) {
+  return array(
+    'content_type' => array(
+      'field_name' => 'content_type',
+      'type' => 'content_type',
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'tripal_no_storage'
+      ),
+      'settings' => array(
+        'semantic_web' => 'rdf:type',
+      ),
+    ),
+  );
+}
+
+/**
+ * Implements hook_create_instance_info().
+ *
+ * This is a Tripal defined hook that supports integration with the
+ * TripalEntity field.
+ */
+function tripal_field_create_instance_info($entity_type, $bundle, $term) {
+  return array(
+    'content_type' => array(
+      'field_name' => 'content_type',
+      'entity_type' => 'TripalEntity',
+      'bundle' => $bundle->name,
+      'label' => 'Resource Type',
+      'description' => '',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'tripal_content_type_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'default' => array(
+          'label' => 'above',
+          'type' => 'tripal_content_type_formatter',
+          'settings' => array(),
+        ),
+      ),
+    ),
+  );
+}
+
 /**
  * Implements hook_field_widget_form().
  */

+ 20 - 43
tripal/tripal.module

@@ -138,9 +138,16 @@ function tripal_menu() {
     'type' => MENU_NORMAL_ITEM,
   );
 
-  // Menu items for facilitating import of extension modules.
   $items['admin/tripal/extension'] = array(
     'title' => 'Extensions',
+    'description' => t("Configuration and management pages for Tripal extension modules."),
+    'weight' => 8,
+    'access arguments' => array('administer tripal'),
+  );
+
+  // Menu items for facilitating import of extension modules.
+  $items['admin/tripal/extension/available'] = array(
+    'title' => 'Available Extensions',
     'description' => t('Look for extensions to add new functionality to this
         site. Tripal can be extended with new functionality developed
         by other Tripal site developers. These include modules with new or
@@ -153,19 +160,19 @@ function tripal_menu() {
     'type' => MENU_NORMAL_ITEM,
     'file' => 'includes/tripal.extensions.inc',
     'file path' => drupal_get_path('module', 'tripal'),
-    'weight' => 100
-  );
-  $items['admin/tripal/extension/import'] = array(
-    'title' => 'Import Extensions',
-    'description' => 'Provides a list of the available extensions that are registered at the tripal.info site. From this page you can easily import or install extensions to your site.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('tripal_extensions_form'),
-    'access arguments' => array('administer tripal'),
-    'type' => MENU_NORMAL_ITEM,
-    'file' =>  'includes/tripal.extensions.inc',
-    'file path' => drupal_get_path('module', 'tripal'),
-    'weight' => -100,
+    'weight' => -100
   );
+//   $items['admin/tripal/extension/import'] = array(
+//     'title' => 'Import Extensions',
+//     'description' => 'Provides a list of the available extensions that are registered at the tripal.info site. From this page you can easily import or install extensions to your site.',
+//     'page callback' => 'drupal_get_form',
+//     'page arguments' => array('tripal_extensions_form'),
+//     'access arguments' => array('administer tripal'),
+//     'type' => MENU_NORMAL_ITEM,
+//     'file' =>  'includes/tripal.extensions.inc',
+//     'file path' => drupal_get_path('module', 'tripal'),
+//     'weight' => -100,
+//   );
 
 
 /*
@@ -515,33 +522,3 @@ function tripal_import_api() {
   module_load_include('inc', 'tripal', 'api/tripal.notice.api');
   module_load_include('inc', 'tripal', 'api/tripal.variables.api');
 }
-
-
-/**
- * Implemenation of hook_add_bundle_fields().
- *
- * In this function we add the type field.
- */
-function tripal_add_bundle_fields($entity_type, $bundle, $term) {
-  $field_name = 'content_type';
-  $bundle_name = $bundle->name;
-
-  // Create the field array.
-  $field_info = array(
-    'field_type' => 'content_type',
-    'widget_type' => 'tripal_content_type_widget',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Record Type',
-    'is_required' => 0,
-    'storage' => 'tripal_no_storage',
-    'field_settings' => array(
-      'semantic_web' => '',
-    ),
-  );
-
-  tripal_add_bundle_field($field_name, $field_info, $entity_type, $bundle_name);
-}
-
-
-

+ 1 - 1
tripal_chado/api/tripal_chado.api.inc

@@ -74,7 +74,7 @@ function tripal_chado_publish_records($values, $job_id = NULL) {
   $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
   $bundle_id = $bundle->id;
   $table = tripal_get_bundle_variable('chado_table', $bundle_id);
-  $column = tripal_get_bundle_variable('chado_column', $bundle_id);
+  $column = tripal_get_bundle_variable('chado_type_column', $bundle_id);
   $cvterm_id = tripal_get_bundle_variable('chado_cvterm_id', $bundle_id);
 
   // Get the table information for the Chado table.

+ 68 - 24
tripal_chado/includes/fields/chado_base__dbxref_id.inc

@@ -20,47 +20,91 @@ class chado_base__dbxref_id extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $settings) {
+  protected function can_attach($entity_type, $bundle, $details) {
 
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // Check the schema for the data table if it does not have
     // a 'dbxref_id' column then we don't want to attach this field.
     $schema = chado_get_schema($table_name);
-    if (!array_key_exists('dbxref_id', $schema['fields'])) {
-      return $field_info;
+    if (array_key_exists('dbxref_id', $schema['fields'])) {
+      return TRUE;
     }
+    return FALSE;
+  }
 
-    // There is an dbxref_id column so attach the field!
-    $field_info = array(
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    };
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
       'field_name' => $table_name . '__dbxref_id',
-      'field_type' => 'chado_base__dbxref_id',
-      'widget_type' => 'chado_base__dbxref_id_widget',
-      'description' => 'This field specifies the unique stable accession (ID) for
-        this record. It requires that this site have a database entry.',
-      'label' => 'Accession',
-      'is_required' => 0,
-      'storage' => 'field_chado_storage',
-      'widget_settings' => array(
-        'display_label' => 1
+      'type' => 'chado_base__dbxref_id',
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
       ),
-      'field_settings' => array(
+      'settings' => array(
         'chado_table' => $table_name,
         'chado_column' => 'dbxref_id',
         'semantic_web' => 'data:2091',
       ),
     );
+  }
 
-    return $field_info;
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    return array(
+      'field_name' => $table_name . '__dbxref_id',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Accession',
+      'description' => 'This field specifies the unique stable accession (ID) for
+        this record. It requires that this site have a database entry.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_base__dbxref_id_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_base__dbxref_id_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
   /**
    * @see TripalField::widget_info()

+ 82 - 32
tripal_chado/includes/fields/chado_base__organism_id.inc

@@ -22,57 +22,107 @@ class chado_base__organism_id extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  public function attach_info($entity_type, $bundle, $settings) {
+  protected function can_attach($entity_type, $bundle, $details) {
 
-    $field_info = array();
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
-
-    // Check the schema for the data table if it does not have
-    // an 'organism_id' column then we don't want to attach this field.
     $schema = chado_get_schema($table_name);
-    if (!array_key_exists('organism_id', $schema['fields'])) {
-      return $field_info;
-    }
 
-    // If this is the organism table then do not attach as that is the
-    // primary key
+    // If this is the organism table then do not attach as the organism_id
+    // field is the primary key and we don't want a field for that.
     if ($table_name == 'organism') {
-      return $field_info;
+      return FALSE;
+    }
+
+    // Check the schema for the data table if it has
+    // an 'organism_id' column then we want to attach this field.
+    if (array_key_exists('organism_id', $schema['fields'])) {
+      return TRUE;
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * @see TripalField::create_info()
+   */
+  public function create_info($entity_type, $bundle, $details) {
+
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => $table_name . '__organism_id',
+      'type' => 'chado_base__organism_id',
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+        'chado_table' => $table_name,
+        'chado_column' => 'organism_id',
+        'semantic_web' => 'local:organism',
+      ),
+    );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  public function create_instance_info($entity_type, $bundle, $details) {
+
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
     }
 
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
     $is_required = FALSE;
+    $schema = chado_get_schema($table_name);
     if (array_key_exists('not null', $schema['fields']['organism_id']) and
         $schema['fields']['organism_id']['not null']) {
       $is_required = TRUE;
     }
 
-    // There is an organism_id column so attach the field!
-    $field_info = array(
+    return array(
       'field_name' => $table_name . '__organism_id',
-      'field_type' => 'chado_base__organism_id',
-      'widget_type' => 'chado_base__organism_id_widget',
-      'description' => 'Select an organism.',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
       'label' => 'Organism',
-      'is_required' => $is_required,
-      'storage' => 'field_chado_storage',
-      'widget_settings' => array(
-        'display_label' => 1
+      'description' => 'Select an organism.',
+      'required' => $is_required,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_base__organism_id_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
       ),
-      'field_settings' => array(
-        'chado_table' => $table_name,
-        'chado_column' => 'organism_id',
-        'semantic_web' => 'local:organism',
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_base__organism_id_formatter',
+          'settings' => array(),
+        ),
       ),
     );
-
-    return $field_info;
   }
 
   /**

+ 77 - 25
tripal_chado/includes/fields/chado_feature__md5checksum.inc

@@ -21,38 +21,90 @@ class chado_feature__md5checksum  extends TripalField {
   }
 
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $settings) {
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     if ($table_name == 'feature') {
-      $field_info = array(
-        'field_name' => $table_name . '__md5checksum',
-        'field_type' => 'chado_feature__md5checksum',
-        'widget_type' => 'chado_feature__md5checksum_widget',
-        'description' => 'The MD5 checksum for the sequence.',
-        'label' => 'The Sequence MD5 Checksum',
-        'is_required' => 0,
-        'storage' => 'field_chado_storage',
-        'widget_settings' => array(
+      return TRUE;
+    }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => $table_name . '__md5checksum',
+      'type' => 'chado_feature__md5checksum',
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+        'chado_table' => $table_name,
+        'chado_column' => 'md5checksum',
+        'semantic_web' => 'data:2190',
+      ),
+    );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => $table_name . '__md5checksum',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Sequence Checksum',
+      'description' => 'The MD5 checksum for the sequence. The checksum here
+        will always be unique for the raw unformatted sequence. To verify that the
+        sequence has not been corrupted, download the raw sequence and use an MD5 tool
+        to calculate the value. If the value calculated is identical the one shown
+        here, then the downloaded sequence is uncorrupted.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_feature__md5checksum_widget',
+        'settings' => array(
           'display_label' => 1,
           'md5_fieldname' => 'feature__md5checksum',
         ),
-        'field_settings' => array(
-          'chado_table' => 'feature',
-          'chado_column' => 'md5checksum',
-          'semantic_web' => 'local:md5_checksum',
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_feature__md5checksum_formatter',
+          'settings' => array(),
         ),
-      );
-    }
-    return $field_info;
+      ),
+    );
   }
 
   /**

+ 72 - 55
tripal_chado/includes/fields/chado_feature__residues.inc

@@ -3,10 +3,7 @@
 class chado_feature__residues extends TripalField {
 
   /**
-   * Implements hook_info() for fields.
-   *
-   * This is a hook provided by the tripal_chado module for offloading the
-   * hook_field_info() hook for each field to specify.
+   * @see TripalField::field_info()
    */
   function field_info() {
     return array(
@@ -24,57 +21,89 @@ class chado_feature__residues extends TripalField {
     );
   }
   /**
-   * Implements hook_attach_info().
-   *
-   * This is a hook provided by the tripal_Chado module. It allows the field
-   * to specify which bundles it will attach to and to specify thee settings.
-   *
-   * @param $entity_type
-   * @param $entity
-   * @param $term
-   *
-   * @return
-   *   A field array
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $settings) {
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
-
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If  this is not the feature table then we don't want to attach.
-    if ($table_name != 'feature') {
-      return $field_info;
+    if ($table_name == 'feature') {
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
-    $field_info = array(
+    return array(
       'field_name' => 'feature__residues',
-      'field_type' => 'chado_feature__residues',
-      'widget_type' => 'chado_feature__residues_widget',
-      'description' => 'An IUPAC compatible residues for this feature.',
-      'label' => 'Sequences',
-      'is_required' => 0,
-      'storage' => 'field_chado_storage',
-      'widget_settings' => array(
-        'display_label' => 1
+      'type' => 'chado_feature__residues',
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
       ),
-      'field_settings' => array(
+      'settings' => array(
         'chado_table' => $table_name,
         'chado_column' => 'residues',
         'semantic_web' => 'SO:0000110',
       ),
     );
-    return $field_info;
   }
   /**
-   * Implements hook_widget_info.
-   *
-   * This is a hook provided by the tripal_chado module for offloading
-   * the hook_field_widget_info() hook for each field to specify.
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => 'feature__residues',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Sequences',
+      'description' => 'All available sequences for this record.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_feature__residues_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_feature__residues_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
+  }
+
+  /**
+   * @see TripalField::widget_info()
    */
   function widget_info() {
     return array(
@@ -83,12 +112,7 @@ class chado_feature__residues extends TripalField {
     );
   }
   /**
-   * Implements hook_formatter_info.
-   *
-   * This is a hook provided by the tripal_chado module for
-   * offloading the hook_field_formatter_info() for each field
-   * to specify.
-   *
+   * @see TripalField::formatter_info()
    */
   function formatter_info() {
     return array(
@@ -97,14 +121,7 @@ class chado_feature__residues extends TripalField {
     );
   }
   /**
-   *
-   * @param unknown $entity_type
-   * @param unknown $entity
-   * @param unknown $field
-   * @param unknown $instance
-   * @param unknown $langcode
-   * @param unknown $items
-   * @param unknown $display
+   * @see TripalField::formatter_view()
    */
   function formatter_view(&$element, $entity_type, $entity, $field,
     $instance, $langcode, $items, $display) {

+ 77 - 28
tripal_chado/includes/fields/chado_feature__seqlen.inc

@@ -18,41 +18,90 @@ class chado_feature__seqlen extends TripalField {
       ),
     );
   }
+
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $settings) {
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
-    // If  this is not the feature table then we don't want to attach.
     if ($table_name == 'feature') {
-      $field_info = array(
-        'field_name' => 'feature__seqlen',
-        'field_type' => 'chado_feature__seqlen',
-        'widget_type' => 'chado_feature__seqlen_widget',
-        'description' => 'The length of the sequence (residues).',
-        'label' => 'Sequence Length',
-        'is_required' => 0,
-        'storage' => 'field_chado_storage',
-        'widget_settings' => array(
-          'display_label' => 1
-        ),
-        'field_settings' => array(
-          'chado_table' => $table_name,
-          'chado_column' => 'seqlen',
-          'semantic_web' => 'data:1249',
-        ),
-      );
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
-    return $field_info;
+    return array(
+      'field_name' => 'feature__seqlen',
+      'type' => 'chado_feature__seqlen',
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+        'chado_table' => $table_name,
+        'chado_column' => 'seqlen',
+        'semantic_web' => 'data:1249',
+      ),
+    );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => 'feature__seqlen',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Raw Sequence Length',
+      'description' => 'The number of residues in the raw sequence.  This length
+        is only for the assigned raw sequence and does not represent the length of any
+        sequences derived from alignments. If this value is zero but aligned sequences
+        are present then this record has no official assigned sequence.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_feature__seqlen_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_feature__seqlen_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
+
   /**
    * @see TripalField::widget_info()
    */

+ 68 - 24
tripal_chado/includes/fields/chado_gene__transcripts.inc

@@ -19,48 +19,92 @@ class chado_gene__transcripts extends TripalField {
       ),
     );
   }
-
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  public function attach_info($entity_type, $bundle, $target) {
-    $field_info = array();
-
-    $table_name = $target['data_table'];
-    $type_table = $target['type_table'];
-    $type_field = $target['field'];
-    $cv_id      = $target['cv_id'];
-    $cvterm_id  = $target['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists or this is not a gene then we don't want to add attach.
     $rel_table = $table_name . '_relationship';
-    if (!chado_table_exists($rel_table) || $bundle->label != 'gene') {
-      return $field_info;
+    if (chado_table_exists($rel_table) and $bundle->label == 'gene') {
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    $rel_table = $table_name . '_relationship';
     $schema = chado_get_schema($rel_table);
     $pkey = $schema['primary key'][0];
 
-    // Initialize the field array.
-    $field_info = array(
+    return array(
       'field_name' => 'gene_transcripts',
-      'field_type' => 'chado_gene__transcripts',
-      'widget_type' => 'chado_gene__transcripts_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Transcripts',
-      'is_required' => 0,
+      'type' => 'chado_gene__transcripts',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
         'chado_table' => $rel_table,
-        'chado_column' => $pkey,
+        'chado_column' => 'md5checksum',
         'base_table' => $table_name,
         'semantic_web' => 'SO:0000673',
       ),
     );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
-    return $field_info;
+    return array(
+      'field_name' => 'gene_transcripts',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Transcripts',
+      'description' => 'These transcripts are associated with this gene.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_gene__transcripts_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_gene__transcripts_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
 
   /**

+ 91 - 40
tripal_chado/includes/fields/chado_linker__contact.inc

@@ -20,6 +20,97 @@ class chado_linker__contact extends TripalField {
       ),
     );
   }
+  /**
+   * @see TripalField::can_attach()
+   */
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];;
+
+    // If the linker table does not exists then we don't want to add attach.
+    $contact_table = $table_name . '_contact';
+    if (chado_table_exists($contact_table)) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    $contact_table = $table_name . '_contact';
+    $schema = chado_get_schema($contact_table);
+    $pkey = $schema['primary key'][0];
+
+    return array(
+      'field_name' => $contact_table,
+      'type' => 'chado_linker__contact',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+        'chado_table' => $contact_table,
+        'chado_column' => $pkey,
+        'base_table' => $table_name,
+        'semantic_web' => 'local:contact'
+      ),
+    );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];;
+
+    $contact_table = $table_name . '_contact';
+
+    return array(
+      'field_name' => $contact_table,
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Contacts',
+      'description' => 'An individual, organization or entity that has had
+        some responsibility for the creation, delivery or maintenance of
+        the associated data.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__contact_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__contact_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
+  }
   /**
    * @see TripalField::widget_info()
    */
@@ -41,47 +132,7 @@ class chado_linker__contact extends TripalField {
       ),
     );
   }
-  /**
-   * @see TripalField::attach_info()
-   */
-  public function attach_info($entity_type, $bundle, $settings) {
-    $field_info = array();
 
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
-
-    // If the linker table does not exists then we don't want to add attach.
-    $contact_table = $table_name . '_contact';
-    if (!chado_table_exists($contact_table)) {
-      return $field_info;
-    }
-
-    $schema = chado_get_schema($contact_table);
-    $pkey = $schema['primary key'][0];
-
-    // Initialize the field array.
-    $field_info = array(
-      'field_name' => $table_name . '_contact',
-      'field_type' => 'chado_linker__contact',
-      'widget_type' => 'chado_linker__contact_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Contacts',
-      'is_required' => 0,
-      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
-        'chado_table' => $contact_table,
-        'chado_column' => $pkey,
-        'base_table' => $table_name,
-        'semantic_web' => 'local:contact'
-      ),
-    );
-    return $field_info;
-  }
 
   /**
    * @see TripalField::formatter_view()

+ 21 - 4
tripal_chado/includes/fields/chado_linker__cvterm.inc

@@ -20,14 +20,31 @@ class chado_linker__cvterm extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $target) {
-    $field_info = array();
+  protected function can_attach($entity_type, $bundle, $details) {
 
     // This field is only attached by the chado_linker__cvterm_addr field.
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    // This field is only attached by the chado_linker__cvterm_addr field.
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
 
-    return $field_info;
+    // This field is only attached by the chado_linker__cvterm_addr field.
   }
   /**
    * @see TripalField::widget_info()

+ 116 - 49
tripal_chado/includes/fields/chado_linker__cvterm_adder.inc

@@ -20,45 +20,88 @@ class chado_linker__cvterm_addr extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $settings) {
-
+  protected function can_attach($entity_type, $bundle, $details) {
     $field_info = array();
 
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
 
     // If the linker table does not exists then we don't want to add attach.
     $cvterm_table = $table_name . '_cvterm';
-    if (!chado_table_exists($cvterm_table)) {
-      return $field_info;
+    if (chado_table_exists($cvterm_table)) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
     }
 
-    // Initialize the field array.
-    $field_info = array(
-      'field_name' => $cvterm_table,
-      'field_type' => 'chado_linker__cvterm_adder',
-      'widget_type' => 'chado_linker__cvterm_adder_widget',
-      'field_settings' => array(
-        'base_table' => $table_name,
-      ),
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => $table_name . '_cvterm',
+      'type' => 'chado_linker__cvterm_adder',
       'cardinality' => 1,
-      'storage' => 'field_chado_storage',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Additional Annotation Types',
-      'is_required' => 0,
-      // This feld is never visible so there are no field settings for
-      // Chado nor the semantiv web.
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+      ),
     );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
-    return $field_info;
+    return array(
+      'field_name' => $table_name . '_cvterm',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Add Annotation Types',
+      'description' => 'Add additional annotations types to this record.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__cvterm_adder_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__cvterm_adder_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
+
   /**
    * @see TripalField::widget_info()
    */
@@ -153,29 +196,53 @@ function chado_linker__cvterm_adder_widget_validate($element, &$form_state) {
     $schema = chado_get_schema($field_name);
     $pkey = $schema['primary key'][0];
 
-    $field_info = array(
-      'field_type' => 'cvterm',
-      'widget_type' => 'tripal_chado_cvterm_widget',
-      'field_settings' => array(
-        'chado_table' => $field_name,
-        'chado_column' => $pkey,
-        'base_table' => $base_table,
-      ),
-      'storage' => 'field_chado_storage',
-      'widget_settings' => array(),
-      'description' => "Annotations from the $cv->name vocabulary",
-      'label' => ucfirst(preg_replace('/_/', ' ', $cv->name)),
-      'is_required' => FALSE,
-      // All annotations are unlimited.
-      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-    );
-    tripal_add_bundle_field($type_field_name, $field_info, $entity_type, $bundle);
+    // Add the field if it doesn't already exists.
+    $field = field_info_field('cvterm');
+    if (!$field) {
+      $create_info = array(
+        'field_name' => 'cvterm',
+        'type' => 'tripal_chado_cvterm_widget',
+        'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+        'locked' => FALSE,
+        'storage' => array(
+          'type' => 'field_chado_storage',
+        ),
+        'settings' => array(
+          'chado_table' => $field_name,
+          'chado_column' => $pkey,
+          'base_table' => $base_table,
+        ),
+      );
+      $field = field_create_field($create_info);
+    }
 
+    // Attach the field to the bundle if it isn't already.
+    if (!$field or !array_key_exists('bundles', $field) or
+        !array_key_exists('TripalEntity', $field['bundles']) or
+        !in_array($bundle_name, $field['bundles']['TripalEntity'])) {
+      $create_instance_info = array(
+        'field_name' => 'cvtmerm',
+        'entity_type' => 'TripalEntity',
+        'bundle' => $bundle->name,
+        'label' => ucfirst(preg_replace('/_/', ' ', $cv->name)),
+        'description' => "Annotations from the $cv->name vocabulary",
+        'required' => FALSE,
+        'settings' => array(),
+        'widget' => array(
+          'type' => 'tripal_chado_cvterm_widget',
+          'settings' => array(
+            'display_label' => 1,
+          ),
+        ),
+        'display' => array(
+          'deafult' => array(
+            'label' => 'above',
+            'type' => 'tripal_chado_cvterm_formatter',
+            'settings' => array(),
+          ),
+        ),
+      );
+      $instance = field_create_instance($create_instance_info);
+    }
   }
-}
-/**
- * Callback function for submitting the chado_linker__cvterm_adder_widget.
- */
-function chado_linker__cvterm_adder_widget_submit($element, &$form_state) {
-
 }

+ 78 - 33
tripal_chado/includes/fields/chado_linker__dbxref.inc

@@ -33,49 +33,94 @@ class chado_linker__dbxref extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $settings) {
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists then we don't want to add attach.
     $dbxref_table = $table_name . '_dbxref';
     if (chado_table_exists($dbxref_table)) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
-      // We already have a dbxref_id field.
-      $schema = chado_get_schema($dbxref_table);
-      $pkey = $schema['primary key'][0];
-
-      // Initialize the field array.
-      $field_info = array(
-        'field_name' => $dbxref_table,
-        'field_type' => 'chado_linker__dbxref',
-        'widget_type' => 'chado_linker__dbxref_widget',
-        'widget_settings' => array('display_label' => 1),
-        'description' => 'This field specifies the IDs where this
-           record may be available in other external online databases.',
-        'label' => 'Cross References',
-        'is_required' => 0,
-        'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-        'storage' => 'field_chado_storage',
-        'field_settings' => array(
-          'chado_table' => $dbxref_table,
-          'chado_column' => $pkey,
-          'base_table' => $table_name,
-          'semantic_web' => 'SBO:0000554',
-        ),
-      );
+    $dbxref_table = $table_name . '_dbxref';
+    $schema = chado_get_schema($dbxref_table);
+    $pkey = $schema['primary key'][0];
 
+    return array(
+      'field_name' => $dbxref_table,
+      'type' => 'chado_linker__dbxref',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+        'chado_table' => $dbxref_table,
+        'chado_column' => $pkey,
+        'base_table' => $table_name,
+        'semantic_web' => 'SBO:0000554',
+      ),
+    );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
     }
 
-    return $field_info;
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    $dbxref_table = $table_name . '_dbxref';
+    return array(
+      'field_name' => $dbxref_table,
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Cross References',
+      'description' => 'The IDs where this record may be available in other external online databases.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__dbxref_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__dbxref_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
+
   /**
    * @see TripalField::widget_info()
    */

+ 97 - 54
tripal_chado/includes/fields/chado_linker__expression.inc

@@ -2,6 +2,9 @@
 
 class chado_linker__expression extends TripalField {
 
+  /**
+   * @see TripalField::field_info()
+   */
   public function field_info() {
     return array(
       'label' => t('Expression'),
@@ -17,70 +20,119 @@ class chado_linker__expression extends TripalField {
       ),
     );
   }
- function widget_info() {
-    return array(
-      'label' => t('Expressions'),
-      'field types' => array('chado_linker__expression'),
-    );
-  }
-
-  public function formatter_info() {
-    return array(
-      'label' => t('Expression'),
-      'field types' => array('chado_linker__expression'),
-      'settings' => array(
-      ),
-    );
-  }
-  public function attach_info($entity_type, $bundle, $settings) {
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+  /**
+   * @see TripalField::can_attach()
+   */
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists then we don't want to add attach.
     $expression_table = $table_name . '_expression';
-    if (!chado_table_exists($expression_table)) {
-      return $field_info;
+    if (chado_table_exists($expression_table)) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
     }
 
-    $schema = chado_get_schema($expression_table);
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    $schema = chado_get_schema('featureloc');
     $pkey = $schema['primary key'][0];
 
-    // Initialize the field array.
-    $field_info = array(
+    return array(
       'field_name' => $table_name . '_expression',
-      'field_type' => 'chado_linker__expression',
-      'widget_type' => 'chado_linker__expression_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Expression',
-      'is_required' => 0,
+      'type' => 'chado_linker__expression',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
-        'chado_table' => $expression_table,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+        'chado_table' => $table_name . '_expression',
         'chado_column' => $pkey,
         'base_table' => $table_name,
         'semantic_web' => 'local:expression',
       ),
     );
-    return $field_info;
   }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
 
-  public function formatter_settings_summary($field, $instance, $view_mode) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    return array(
+      'field_name' => $table_name . '_expression',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Expression',
+      'description' => 'Information about the expression of this record.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__expression_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__expression_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
 
-  public function formatter_settings_form($field, $instance,
-      $view_mode, $form, &$form_state) {
-
+  /**
+   * @see TripalField::widget_info()
+   */
+ function widget_info() {
+    return array(
+      'label' => t('Expressions'),
+      'field types' => array('chado_linker__expression'),
+    );
   }
 
+  /**
+   * @see TripalField::formatter_info()
+   */
+  public function formatter_info() {
+    return array(
+      'label' => t('Expression'),
+      'field types' => array('chado_linker__expression'),
+      'settings' => array(
+      ),
+    );
+  }
 
+  /**
+   * @see TripalField::formatter_view()
+   */
   public function formatter_view(&$element, $entity_type, $entity,
       $field, $instance, $langcode, $items, $display) {
 
@@ -152,13 +204,9 @@ class chado_linker__expression extends TripalField {
     );
   }
 
-
-  public function widget_form(&$widget, &$form, &$form_state, $field, $instance,
-      $langcode, $items, $delta, $element) {
-
-
-  }
-
+  /**
+   * @see TripalField::load()
+   */
   public function load($field, $entity, $details) {
     $record = $details['record'];
 
@@ -232,9 +280,4 @@ class chado_linker__expression extends TripalField {
     }
   }
 
-  public function settings_form($field, $instance, $has_data) {
-
-  }
-
-
 }

+ 67 - 23
tripal_chado/includes/fields/chado_linker__featureloc.inc

@@ -19,47 +19,91 @@ class chado_linker__featureloc extends TripalField {
       ),
     );
   }
-
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  public function attach_info($entity_type, $bundle, $target) {
-    $field_info = array();
-
-    $table_name = $target['data_table'];
-    $type_table = $target['type_table'];
-    $type_field = $target['field'];
-    $cv_id      = $target['cv_id'];
-    $cvterm_id  = $target['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If  this is not the feature table then we don't want to attach.
-    if ($table_name != 'feature') {
-      return $field_info;
+    if ($table_name == 'feature') {
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     $schema = chado_get_schema('featureloc');
     $pkey = $schema['primary key'][0];
 
-    // Initialize the field array.
-    $field_info = array(
+    return array(
       'field_name' => 'featureloc',
-      'field_type' => 'chado_linker__featureloc',
-      'widget_type' => 'chado_linker__featureloc_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Aligned Locations',
-      'is_required' => 0,
+      'type' => 'chado_linker__featureloc',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
         'chado_table' => 'featureloc',
         'chado_column' => $pkey,
         'base_table' => 'feature',
         'semantic_web' => 'SO:position_of',
       ),
     );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
-    return $field_info;
+    return array(
+      'field_name' => 'featureloc',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Aligned Locations',
+      'description' => 'The locations on other genomic sequences where this
+        record has been aligned.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__featureloc_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__featureloc_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
 
   /**

+ 68 - 22
tripal_chado/includes/fields/chado_linker__genotype.inc

@@ -42,45 +42,91 @@ class chado_linker__genotype extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  public function attach_info($entity_type, $bundle, $settings) {
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists then we don't want to add attach.
     $genotype_table = $table_name . '_genotype';
-    if (!chado_table_exists($genotype_table)) {
-      return $field_info;
+    if (chado_table_exists($genotype_table)) {
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    $genotype_table = $table_name . '_genotype';
     $schema = chado_get_schema($genotype_table);
     $pkey = $schema['primary key'][0];
 
-    // Initialize the field array.
-    $field_info = array(
+    return array(
       'field_name' => $table_name . '__genotype',
-      'field_type' => 'chado_linker__genotype',
-      'widget_type' => 'chado_linker__genotype_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Genotypes',
-      'is_required' => 0,
+      'type' => 'chado_feature__md5checksum',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
         'chado_table' => $genotype_table,
         'chado_column' => $pkey,
         'semantic_web' => 'SO:0001027',
         'base_table' => $table_name,
       ),
     );
-    return $field_info;
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => $table_name . '__genotype',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Genotypes',
+      'description' => 'The genotypes associated with this record.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__genotype_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__genotype_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
 
   /**

+ 69 - 22
tripal_chado/includes/fields/chado_linker__phenotype.inc

@@ -42,45 +42,92 @@ class chado_linker__phenotype extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  public function attach_info($entity_type, $bundle, $settings) {
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists then we don't want to add attach.
     $phenotype_table = $table_name . '_phenotype';
-    if (!chado_table_exists($phenotype_table)) {
-      return $field_info;
+    if (chado_table_exists($phenotype_table)) {
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    $phenotype_table = $table_name . '_phenotype';
     $schema = chado_get_schema($phenotype_table);
     $pkey = $schema['primary key'][0];
 
-    // Initialize the field array.
-    $field_info = array(
+    return array(
       'field_name' => $table_name . '__phenotype',
-      'field_type' => 'chado_linker__phenotype',
-      'widget_type' => 'chado_linker__phenotype_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Phenotypes',
-      'is_required' => 0,
+      'type' => 'chado_linker__phenotype',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
         'chado_table' => $phenotype_table,
         'chado_column' => $pkey,
         'base_table' => $table_name,
         'semantic_web' => 'SBO:0000358',
       ),
     );
-    return $field_info;
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => $table_name . '__phenotype',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Phenotypes',
+      'description' => 'The phenotypes associated with this record.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__phenotype_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__phenotype_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
+
   }
 
   /**

+ 264 - 283
tripal_chado/includes/fields/chado_linker__prop.inc

@@ -1,317 +1,298 @@
 <?php
-/**
- * Implements hook_info() for fields.
- *
- * This is a hook provided by the tripal_chado module for offloading the
- * hook_field_info() hook for each field to specify.
- */
-function chado_linker__prop_info() {
-  return array(
-    'label' => t('Add a Property'),
-    'description' => t('Add details about this property.'),
-    'default_widget' => 'chado_linker__prop_widget',
-    'default_formatter' => 'chado_linker__prop_formatter',
-    'settings' => array(),
-    'storage' => array(
-      'type' => 'field_chado_storage',
-      'module' => 'tripal_chado',
-      'active' => TRUE
-    ),
-  );
-}
-/**
- * Implements hook_attach_info().
- *
- * This is a hook provided by the tripal_Chado module. It allows the field
- * to specify which bundles it will attach to and to specify thee settings.
- *
- * @param $entity_type
- * @param $entity
- * @param $term
- *
- * @return
- *   A field array
- */
-function chado_linker__prop_attach_info($entity_type, $bundle, $target) {
-  $field_info = array();
 
-  // This field is only attached by the chado_linker__prop_addr field.
-
-  return $field_info;
-}
-/**
- * Implements hook_widget_info.
- *
- * This is a hook provided by the tripal_chado module for offloading
- * the hook_field_widget_info() hook for each field to specify.
- */
-function chado_linker__prop_widget_info() {
-  return array(
-    'label' => t('Property'),
-    'field types' => array('chado_linker__prop'),
-  );
-}
-/**
- * Implements hook_formatter_info.
- *
- * This is a hook provided by the tripal_chado module for
- * offloading the hook_field_formatter_info() for each field
- * to specify.
- *
- */
-function chado_linker__prop_formatter_info() {
-  return array(
-    'label' => t('Property'),
-    'field types' => array('chado_linker__prop'),
-    'settings' => array(
-    ),
-  );
-}
-/**
- *
- * @param unknown $entity_type
- * @param unknown $entity
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $display
- */
-function chado_linker__prop_formatter(&$element, $entity_type, $entity, $field,
-  $instance, $langcode, $items, $display) {
+class chado_linker__prop extends TripalField {
+  /**
+   * @see TripalField::field_info()
+   */
+  function field_info() {
+    return array(
+      'label' => t('Add a Property'),
+      'description' => t('Add details about this property.'),
+      'default_widget' => 'chado_linker__prop_widget',
+      'default_formatter' => 'chado_linker__prop_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    );
+  }
+  /**
+   * @see TripalField::can_attach()
+   */
+  protected function can_attach($entity_type, $bundle, $details) {
+    // This field is only attached by the chado_linker__prop_addr field.
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
 
-  $field_name = $field['field_name'];
-  $chado_table = $field['settings']['chado_table'];
+    // This field is only attached by the chado_linker__prop_addr field.
 
-  $properties = array();
-  foreach ($items as $delta => $item) {
-    $properties[] = $item[$chado_table . '__value'];
   }
-  $content = implode(', ', $properties);
-  $element[$delta] = array(
-    '#type' => 'markup',
-    '#markup' => $content,
-  );
-}
-/**
- *
- * @param unknown $field_name
- * @param unknown $widget
- * @param unknown $form
- * @param unknown $form_state
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $delta
- * @param unknown $element
- */
-function chado_linker__prop_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-  $entity = $form['#entity'];
-  $field_name = $field['field_name'];
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
 
-  // Get the record and table mapping info.
-  $chado_table = $entity->chado_table;
-  $chado_column = $entity->chado_column;
-  $chado_record = $entity->chado_record;
+    // This field is only attached by the chado_linker__prop_addr field.
 
-  $matches = array();
-  preg_match('/(.*?)__(\d+)/', $field_name, $matches);
-  // If the field name is not properly formatted then we can't tell what
-  // table and type this is.  So just return.
-  if (count($matches) != 3) {
-    return $widget;
   }
-  $table_name = $matches[1];
-  $cvterm_id = $matches[2];
+  /**
+   * @see TripalField::attach_info()
+   */
+  function attach_info($entity_type, $bundle, $target) {
+    $field_info = array();
 
-  // Get the name of the pkey field for this property table and the name
-  // of the FK field that links to the base table.
-  $schema = chado_get_schema($table_name);
-  $pkey = $schema['primary key'][0];
-  $lfkey_field = key($schema['foreign keys'][$chado_table]['columns']);
-  $rfkey_field = $schema['foreign keys'][$chado_table]['columns'][$lfkey_field];
+    // This field is only attached by the chado_linker__prop_addr field.
 
-  // Get the field defaults.
-  $fk_value = '';
-  $propval = '';
-  if (array_key_exists($delta, $items)) {
-    $propval = $items[$delta][$table_name . '__value'];
+    return $field_info;
+  }
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('Property'),
+      'field types' => array('chado_linker__prop'),
+    );
   }
-  if ($chado_record) {
-    $fk_value = $chado_record->$rfkey_field;
+  /**
+   * @see TripalField::formatter_info()
+   */
+  function formatter_info() {
+    return array(
+      'label' => t('Property'),
+      'field types' => array('chado_linker__prop'),
+      'settings' => array(
+      ),
+    );
   }
+  /**
+   * @see TripalField::formatter_view()
+   */
+  function formatter_view(&$element, $entity_type, $entity, $field,
+    $instance, $langcode, $items, $display) {
 
+    $field_name = $field['field_name'];
+    $chado_table = $field['settings']['chado_table'];
 
-  // The group of elements all-together need some extra functionality
-  // after building up the full list (like draggable table rows).
-  $widget['#theme'] = 'field_multiple_value_form';
-  $widget['#title'] = $element['#title'];
-  $widget['#description'] = $element['#description'];
-  $widget['#field_name'] = $element['#field_name'];
-  $widget['#language'] = $element['#language'];
-  $widget['#weight'] = isset($element['#weight']) ? $element['#weight'] : 0;
-  $widget['#element_validate'] = array('chado_linker__prop_widget_validate');
-  $widget['#cardinality'] = 1;
+    $properties = array();
+    foreach ($items as $delta => $item) {
+      $properties[] = $item[$chado_table . '__value'];
+    }
+    $content = implode(', ', $properties);
+    $element[$delta] = array(
+      '#type' => 'markup',
+      '#markup' => $content,
+    );
+  }
+  /**
+   * @see TripalField::widget_form()
+   */
+  function widget_form(&$widget, &$form, &$form_state, $field, $instance,
+      $langcode, $items, $delta, $element) {
 
-  $widget['value'] = array(
-    '#type' => 'value',
-    '#value' => $items[$delta]['value'],
-  );
+    $entity = $form['#entity'];
+    $field_name = $field['field_name'];
 
-  $widget[$table_name . '__' . $pkey] = array(
-    '#type' => 'hidden',
-    '#default_value' => !empty($items[$delta]['value']) ? $items[$delta]['value'] : '',
-  );
-  $widget[$table_name . '__' . $lfkey_field] = array(
-    '#type' => 'hidden',
-    '#value' => $fk_value,
-  );
-  $widget[$table_name . '__value'] = array(
-    '#type' => 'textfield',
-    '#default_value' => $propval,
-  );
-  $widget[$table_name . '__type_id'] = array(
-    '#type' => 'hidden',
-    '#value' => $cvterm_id,
-  );
-  $widget[$table_name . '__rank'] = array(
-    '#type' => 'hidden',
-    '#value' => $delta,
-  );
-  return $widget;
-}
+    // Get the record and table mapping info.
+    $chado_table = $entity->chado_table;
+    $chado_column = $entity->chado_column;
+    $chado_record = $entity->chado_record;
 
-/**
- *
- * @param unknown $form
- * @param unknown $form_state
- */
-function chado_linker__prop_widget_form_ajax_callback($form, $form_state) {
-  $field_name = $form_state['triggering_element']['#parents'][0];
-  return $form[$field_name];
-}
-/**
- * Callback function for validating the chado_linker__prop_widget.
- */
-function chado_linker__prop_widget_validate($element, &$form_state) {
-  $field_name = $element['#field_name'];
-  $delta = $element['#delta'];
-  $entity = $element['#entity'];
-  $matches = array();
+    $matches = array();
+    preg_match('/(.*?)__(\d+)/', $field_name, $matches);
+    // If the field name is not properly formatted then we can't tell what
+    // table and type this is.  So just return.
+    if (count($matches) != 3) {
+      return $widget;
+    }
+    $table_name = $matches[1];
+    $cvterm_id = $matches[2];
 
-  // Get the record and table mapping info.
-  $chado_table = $entity->chado_table;
-  $chado_column = $entity->chado_column;
+    // Get the name of the pkey field for this property table and the name
+    // of the FK field that links to the base table.
+    $schema = chado_get_schema($table_name);
+    $pkey = $schema['primary key'][0];
+    $lfkey_field = key($schema['foreign keys'][$chado_table]['columns']);
+    $rfkey_field = $schema['foreign keys'][$chado_table]['columns'][$lfkey_field];
 
-  // Get the table name and cvterm_id for this field.
-  preg_match('/(.*?)__(\d+)/', $field_name, $matches);
-  $table_name = $matches[1];
-  $cvterm_id = $matches[2];
+    // Get the field defaults.
+    $fk_value = '';
+    $propval = '';
+    if (array_key_exists($delta, $items)) {
+      $propval = $items[$delta][$table_name . '__value'];
+    }
+    if ($chado_record) {
+      $fk_value = $chado_record->$rfkey_field;
+    }
 
-  // Get the name of the pkey field for this property table and the name
-  // of the FK field that links to the base table.
-  $schema = chado_get_schema($table_name);
-  $pkey = $schema['primary key'][0];
-  $lfkey_field = key($schema['foreign keys'][$chado_table]['columns']);
 
-  // If we don't have a property value then we need to set all other fields
-  // to be empty so that when the module tries to save the field on the
-  // entity it won't try to save a partial record.
-  $pkey_val = tripal_chado_get_field_form_values($field_name, $form_state, $delta);
-  $prop_value = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $table_name . "__value");
-  $fk_val = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $table_name . '__' . $lfkey_field);
-  $type_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $table_name . '__type_id');
+    // The group of elements all-together need some extra functionality
+    // after building up the full list (like draggable table rows).
+    $widget['#theme'] = 'field_multiple_value_form';
+    $widget['#title'] = $element['#title'];
+    $widget['#description'] = $element['#description'];
+    $widget['#field_name'] = $element['#field_name'];
+    $widget['#language'] = $element['#language'];
+    $widget['#weight'] = isset($element['#weight']) ? $element['#weight'] : 0;
+    $widget['#element_validate'] = array('chado_linker__prop_widget_validate');
+    $widget['#cardinality'] = 1;
 
-  if (!$prop_value) {
-    tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__' . $lfkey_field);
-    tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__value');
-    tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__type_id');
-    tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__rank');
-  }
-  else {
-    $rank = tripal_chado_get_field_form_values($field_name, $form_state, $delta, '_weight');
-    tripal_chado_set_field_form_values($field_name, $form_state, $rank, $delta, $table_name . '__rank');
-  }
-  // Remove the properties for this record. We will re-add it. Otherwise,
-  // if we change ranks, we wind up with multiple records in the property table.
-  if ($pkey_val) {
-    $match = array(
-      $pkey => $pkey_val
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['value'],
+    );
+
+    $widget[$table_name . '__' . $pkey] = array(
+      '#type' => 'hidden',
+      '#default_value' => !empty($items[$delta]['value']) ? $items[$delta]['value'] : '',
+    );
+    $widget[$table_name . '__' . $lfkey_field] = array(
+      '#type' => 'hidden',
+      '#value' => $fk_value,
+    );
+    $widget[$table_name . '__value'] = array(
+      '#type' => 'textfield',
+      '#default_value' => $propval,
     );
-    chado_delete_record($table_name, $match);
+    $widget[$table_name . '__type_id'] = array(
+      '#type' => 'hidden',
+      '#value' => $cvterm_id,
+    );
+    $widget[$table_name . '__rank'] = array(
+      '#type' => 'hidden',
+      '#value' => $delta,
+    );
+    return $widget;
   }
-}
-/**
- * Callback function for submitting the chado_linker__prop_widget.
- */
-function chado_linker__prop_widget_submit($element, &$form_state) {
-}
 
-/**
- * Loads the field values with appropriate data.
- *
- * This function is called by the tripal_chado_field_storage_load() for
- * each property managed by the field_chado_storage storage type.  This is
- * an optional hook function that is only needed if the field has
- * multiple form elements.
- *
- * @param $field
- * @param $entity
- * @param $base_table
- * @param $record
- */
-function chado_linker__prop_load($field, $entity, $base_table, $record) {
 
-  $field_name = $field['field_name'];
-  $field_type = $field['type'];
-  $field_table = $field['settings']['chado_table'];
-  $field_column = $field['settings']['chado_column'];
+  /**
+   * @see TripalField::validate()
+   */
+  function validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
+    $field_name = $element['#field_name'];
+    $delta = $element['#delta'];
+    $entity = $element['#entity'];
+    $matches = array();
+
+    // Get the record and table mapping info.
+    $chado_table = $entity->chado_table;
+    $chado_column = $entity->chado_column;
 
-  $matches = array();
-  preg_match('/(.*?)__(\d+)/', $field_name, $matches);
-  $table_name = $matches[1];
-  $cvterm_id = $matches[2];
+    // Get the table name and cvterm_id for this field.
+    preg_match('/(.*?)__(\d+)/', $field_name, $matches);
+    $table_name = $matches[1];
+    $cvterm_id = $matches[2];
 
-  // Get the FK that links to the base record.
-  $schema = chado_get_schema($field_table);
-  $pkey = $schema['primary key'][0];
-  $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
-  $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
+    // Get the name of the pkey field for this property table and the name
+    // of the FK field that links to the base table.
+    $schema = chado_get_schema($table_name);
+    $pkey = $schema['primary key'][0];
+    $lfkey_field = key($schema['foreign keys'][$chado_table]['columns']);
 
-  // Set some defaults for the empty record.
-  $entity->{$field_name}['und'][0] = array(
-    'value' => '',
-    $field_table . '__' . $pkey => '',
-    $field_table . '__' . $fkey_lcolumn => '',
-    $field_table . '__value' => '',
-    $field_table . '__type_id' => '',
-    $field_table . '__rank' => '',
-  );
+    // If we don't have a property value then we need to set all other fields
+    // to be empty so that when the module tries to save the field on the
+    // entity it won't try to save a partial record.
+    $pkey_val = tripal_chado_get_field_form_values($field_name, $form_state, $delta);
+    $prop_value = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $table_name . "__value");
+    $fk_val = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $table_name . '__' . $lfkey_field);
+    $type_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $table_name . '__type_id');
 
-  // Get the properties associated with this base record for this fields
-  // given type.
-  $columns = array('*');
-  $match = array(
-    $fkey_lcolumn => $record->$fkey_rcolumn,
-    'type_id' => $cvterm_id,
-  );
-  $options = array(
-    'return_array' => TRUE,
-    'order_by' => array('rank' => 'ASC')
-  );
-  $properties = chado_select_record($field_table, $columns, $match, $options);
-  for ($i = 0; $i < count($properties); $i++) {
-    $property = $properties[$i];
-    foreach ($schema['fields'] as $fname => $details) {
-      $entity->{$field_name}['und'][$i] = array(
-        'value' => array(),
-        $field_table . '__' . $pkey => $property->$pkey,
-        $field_table . '__' . $fkey_lcolumn => $property->$fkey_lcolumn,
-        $field_table . '__value' => $property->value,
-        $field_table . '__type_id' => $property->type_id,
-        $field_table . '__rank' => $property->rank,
+    if (!$prop_value) {
+      tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__' . $lfkey_field);
+      tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__value');
+      tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__type_id');
+      tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__rank');
+    }
+    else {
+      $rank = tripal_chado_get_field_form_values($field_name, $form_state, $delta, '_weight');
+      tripal_chado_set_field_form_values($field_name, $form_state, $rank, $delta, $table_name . '__rank');
+    }
+    // Remove the properties for this record. We will re-add it. Otherwise,
+    // if we change ranks, we wind up with multiple records in the property table.
+    if ($pkey_val) {
+      $match = array(
+        $pkey => $pkey_val
       );
+      chado_delete_record($table_name, $match);
+    }
+  }
+  /**
+   * @see TripalField::load()
+   */
+  function load($field, $entity, $details) {
+
+    $field_name = $details['field_name'];
+    $field_type = $details['type'];
+    $field_table = $details['settings']['chado_table'];
+    $field_column = $details['settings']['chado_column'];
+
+    $matches = array();
+    preg_match('/(.*?)__(\d+)/', $field_name, $matches);
+    $table_name = $matches[1];
+    $cvterm_id = $matches[2];
+
+    // Get the FK that links to the base record.
+    $schema = chado_get_schema($field_table);
+    $pkey = $schema['primary key'][0];
+    $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
+    $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
+
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = array(
+      'value' => '',
+      $field_table . '__' . $pkey => '',
+      $field_table . '__' . $fkey_lcolumn => '',
+      $field_table . '__value' => '',
+      $field_table . '__type_id' => '',
+      $field_table . '__rank' => '',
+    );
+
+    // Get the properties associated with this base record for this fields
+    // given type.
+    $columns = array('*');
+    $match = array(
+      $fkey_lcolumn => $record->$fkey_rcolumn,
+      'type_id' => $cvterm_id,
+    );
+    $options = array(
+      'return_array' => TRUE,
+      'order_by' => array('rank' => 'ASC')
+    );
+    $properties = chado_select_record($field_table, $columns, $match, $options);
+    for ($i = 0; $i < count($properties); $i++) {
+      $property = $properties[$i];
+      foreach ($schema['fields'] as $fname => $details) {
+        $entity->{$field_name}['und'][$i] = array(
+          'value' => array(),
+          $field_table . '__' . $pkey => $property->$pkey,
+          $field_table . '__' . $fkey_lcolumn => $property->$fkey_lcolumn,
+          $field_table . '__value' => $property->value,
+          $field_table . '__type_id' => $property->type_id,
+          $field_table . '__rank' => $property->rank,
+        );
+      }
     }
   }
 }
+/**
+ *
+ * @param unknown $form
+ * @param unknown $form_state
+ */
+function chado_linker__prop_widget_form_ajax_callback($form, $form_state) {
+  $field_name = $form_state['triggering_element']['#parents'][0];
+  return $form[$field_name];
+}

+ 122 - 44
tripal_chado/includes/fields/chado_linker__prop_adder.inc

@@ -21,41 +21,86 @@ class chado_linker__prop_adder extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
- */
-  function attach_info($entity_type, $bundle, $target) {
-    $field_info = array();
-
-    $table_name = $target['data_table'];
-    $type_table = $target['type_table'];
-    $type_field = $target['field'];
-    $cv_id      = $target['cv_id'];
-    $cvterm_id  = $target['cvterm_id'];
+   * @see TripalField::can_attach()
+   */
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists then we don't want to add attach.
     $prop_table = $table_name . 'prop';
-    if (!chado_table_exists($prop_table)) {
-      return $field_info;
+    if (chado_table_exists($prop_table)) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
     }
 
-    // Initialize the field array.
-    $field_info = array(
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    $prop_table = $table_name . 'prop';
+    return array(
       'field_name' => $prop_table,
-      'field_type' => 'chado_linker__prop_adder',
-      'widget_type' => 'chado_linker__prop_adder_widget',
-      'field_settings' => array(
-        'base_table' => $table_name,
-      ),
+      'type' => 'chado_linker__prop_adder',
       'cardinality' => 1,
-      'storage' => 'field_chado_storage',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Additional Properties',
-      'is_required' => 0,
-      // This feld is never visible so there are no field settings for
-      // Chado nor the semantic web.
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+      ),
+    );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    $prop_table = $table_name . 'prop';
+    return array(
+      'field_name' => $prop_table,
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Add Properties',
+      'description' => 'Add additional property types to this record.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__prop_adder_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__prop_adder_formatter',
+          'settings' => array(),
+        ),
+      ),
     );
-    return $field_info;
   }
   /**
    * @see TripalField::widget_info()
@@ -146,23 +191,56 @@ function chado_linker__prop_adder_widget_validate($element, &$form_state) {
           $schema = chado_get_schema($field_name);
           $pkey = $schema['primary key'][0];
 
-          $field_info = array(
-            'field_type' => 'kvproperty',
-            'widget_type' => 'tripal_chado_kvproperty_widget',
-            'field_settings' => array(
-              'chado_table' => $field_name,
-              'chado_column' => $pkey,
-              'base_table' => $base_table,
-            ),
-            'storage' => 'field_chado_storage',
-            'widget_settings' => array(),
-            'description' => $term[0]->definition ? $term[0]->definition : '',
-            'label' => ucfirst(preg_replace('/_/', ' ', $term[0]->name)),
-            'is_required' => FALSE,
-            // All properties are unlimited.
-            'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-          );
-          tripal_add_bundle_field($prop_field_name, $field_info, $entity_type, $bundle);
+          // Add the field if it doesn't already exists.
+          $field = field_info_field('cvterm');
+          if (!$field) {
+            $create_info = array(
+              'field_name' => 'property-' . $term[0]->cvterm_id,
+              'type' => 'tripal_chado_kvproperty_widget',
+              'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+              'locked' => FALSE,
+              'storage' => array(
+                'type' => 'field_chado_storage',
+              ),
+              'settings' => array(
+                'chado_table' => $field_name,
+                'chado_column' => $pkey,
+                'base_table' => $base_table,
+                'semantic_web' => '',
+              ),
+            );
+            $field = field_create_field($create_info);
+          }
+
+          // Attach the field to the bundle if it isn't already.
+          if (!$field and array_key_exists('bundles', $field) or
+              !array_key_exists('TripalEntity', $field['bundles']) or
+              !in_array($bundle_name, $field['bundles']['TripalEntity'])) {
+
+            $create_instance_info = array(
+              'field_name' => 'property-' . $term[0]->cvterm_id,
+              'entity_type' => 'TripalEntity',
+              'bundle' => $bundle->name,
+              'label' => ucfirst(preg_replace('/_/', ' ', $term[0]->name)),
+              'description' => $term[0]->definition ? $term[0]->definition : '',
+              'required' => FALSE,
+              'settings' => array(),
+              'widget' => array(
+                'type' => 'tripal_chado_kvproperty_widget',
+                'settings' => array(
+                  'display_label' => 1,
+                ),
+              ),
+              'display' => array(
+                'deafult' => array(
+                  'label' => 'above',
+                  'type' => 'tripal_chado_kvproperty_formatter',
+                  'settings' => array(),
+                ),
+              ),
+            );
+            $instance = field_create_instance($create_instance_info);
+          }
         }
         else if (count($term) > 1) {
           form_set_error(implode('][', $element ['#parents']) . '][value', t("This term is present in multiple vocabularies. Please select the appropriate one."));

+ 71 - 23
tripal_chado/includes/fields/chado_linker__pub.inc

@@ -20,45 +20,93 @@ class chado_linker_pub extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $target) {
-    $field_info = array();
-
-    $table_name = $target['data_table'];
-    $type_table = $target['type_table'];
-    $type_field = $target['field'];
-    $cv_id      = $target['cv_id'];
-    $cvterm_id  = $target['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists then we don't want to add attach.
     $pub_table = $table_name . '_pub';
-    if (!chado_table_exists($pub_table)) {
-      return $field_info;
+    if (chado_table_exists($pub_table)) {
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    $pub_table = $table_name . '_pub';
     $schema = chado_get_schema($pub_table);
     $pkey = $schema['primary key'][0];
-
-    // Initialize the field array.
-    $field_info = array(
+    return array(
       'field_name' => $table_name . '__pub',
-      'field_type' => 'chado_linker__pub',
-      'widget_type' => 'chado_linker__pub_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Publications',
-      'is_required' => 0,
+      'type' => 'chado_linker__pub',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
         'chado_table' => $pub_table,
         'chado_column' => $pkey,
         'base_table' => $table_name,
         'semantic_web' => 'schema:publication',
       ),
     );
-    return $field_info;
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => $table_name . '__pub',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Publications',
+      'description' => 'This record has been referenced or is sourced from
+        these publications.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__pub_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__pub_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
+
   }
   /**
    * @see TripalField::widget_info()

+ 77 - 27
tripal_chado/includes/fields/chado_linker__relationship.inc

@@ -18,50 +18,93 @@ class chado_linker__relationship extends TripalField {
       ),
     );
   }
-
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $target) {
-    $field_info = array();
-
-    $table_name = $target['data_table'];
-    $type_table = $target['type_table'];
-    $type_field = $target['field'];
-    $cv_id      = $target['cv_id'];
-    $cvterm_id  = $target['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists then we don't want to add attach.
     $rel_table = $table_name . '_relationship';
-    if (!chado_table_exists($rel_table)) {
-      return $field_info;
+    if (chado_table_exists($rel_table)) {
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    $rel_table = $table_name . '_relationship';
     $schema = chado_get_schema($rel_table);
     $pkey = $schema['primary key'][0];
-
-    // Initialize the field array.
-    $field_info = array(
+    return array(
       'field_name' => $table_name . '_relationship',
-      'field_type' => 'chado_linker__relationship',
-      'widget_type' => 'chado_linker__relationship_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => 'A generic field for displaying relationships between data types',
-      'label' => 'Relationships',
-      'is_required' => 0,
+      'type' => 'chado_linker__relationship',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
         'chado_table' => $rel_table,
         'chado_column' => $pkey,
         'base_table' => $table_name,
         'semantic_web' => 'SBO:0000374',
       ),
     );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
 
-    return $field_info;
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    return array(
+      'field_name' => $table_name . '_relationship',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Relationships',
+      'description' => 'Other records with relationships to this record.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__relationship_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__relationship_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
+
   /**
    * @see TripalField::widget_info()
    */
@@ -200,8 +243,12 @@ class chado_linker__relationship extends TripalField {
       $type_id = $items[$delta][$field_table . '__type_id'];
       $object_id = $items[$delta][$field_table . '__object_id'];
 
-      $value = $items[$delta][$field_table . '__value'];
-      $rank = $items[$delta][$field_table . '__rank'];
+      if (array_key_exists('value', $schema['fields'])) {
+        $value = $items[$delta][$field_table . '__value'];
+      }
+      if (array_key_exists('rank', $schema['fields'])) {
+        $rank = $items[$delta][$field_table . '__rank'];
+      }
 
       $object_uniquename = $items[$delta]['object_name'];
       $subject_uniquename = $items[$delta]['subject_name'];
@@ -273,10 +320,13 @@ class chado_linker__relationship extends TripalField {
       '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/$base_table",
     );
     $default_cv = tripal_get_default_cv($field_table, 'type_id');
+    $options = array();
     if (!$default_cv) {
       drupal_set_message("There is no default vocabulary set for the relationships....");
     }
-    $options = tripal_get_cvterm_select_options($default_cv->cv_id, TRUE);
+    else {
+      $options = tripal_get_cvterm_select_options($default_cv->cv_id, TRUE);
+    }
     $widget['type_name'] = array(
       '#type' => 'select',
       '#title' => t('Type'),

+ 69 - 22
tripal_chado/includes/fields/chado_linker__synonym.inc

@@ -20,45 +20,92 @@ class chado_linker__synonym extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  function attach_info($entity_type, $bundle, $target) {
-    $field_info = array();
-
-    $table_name = $target['data_table'];
-    $type_table = $target['type_table'];
-    $type_field = $target['field'];
-    $cv_id      = $target['cv_id'];
-    $cvterm_id  = $target['cvterm_id'];
+  protected function can_attach($entity_type, $bundle, $details) {
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     // If the linker table does not exists then we don't want to add attach.
     $syn_table = $table_name . '_synonym';
-    if (!chado_table_exists($syn_table)) {
-      return $field_info;
+    if (chado_table_exists($syn_table)) {
+      return TRUE;
     }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
+    $syn_table = $table_name . '_synonym';
     $schema = chado_get_schema($syn_table);
     $pkey = $schema['primary key'][0];
 
-    // Initialize the field array.
-    $field_info = array(
+    return array(
       'field_name' => $table_name . '_synonym',
-      'field_type' => 'chado_linker__synonym',
-      'widget_type' => 'chado_linker__synonym_widget',
-      'widget_settings' => array('display_label' => 1),
-      'description' => '',
-      'label' => 'Synonyms',
-      'is_required' => 0,
+      'type' => 'chado_linker__synonym',
       'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-      'storage' => 'field_chado_storage',
-      'field_settings' => array(
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
         'chado_table' => $syn_table,
         'chado_column' => $pkey,
         'base_table' => $table_name,
         'semantic_web' => 'schema:alternateName',
       ),
     );
-    return $field_info;
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => $table_name . '_synonym',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Synonyms',
+      'description' => 'Alternate names, aliases or synonyms for this record.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_linker__synonym_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_linker__synonym_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
   }
   /**
    * @see TripalField::widget_info()

+ 74 - 27
tripal_chado/includes/fields/chado_organism__type_id.inc

@@ -21,41 +21,88 @@ class chado_organism__type_id extends TripalField {
     );
   }
   /**
-   * @see TripalField::attach_info()
+   * @see TripalField::can_attach()
    */
-  public function attach_info($entity_type, $bundle, $settings) {
-
-    $field_info = array();
-
-    $table_name = $settings['data_table'];
-    $type_table = $settings['type_table'];
-    $type_field = $settings['field'];
-    $cv_id      = $settings['cv_id'];
-    $cvterm_id  = $settings['cvterm_id'];
+  function can_attach($entity_type, $bundle, $details){
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
 
     $schema = chado_get_schema($table_name);
 
     // If this is the organism table and Chado v1.3 then attach.
     if ($table_name == 'organism' and array_key_exists('type_id', $schema['fields'])) {
-      $field_info = array(
-        'field_name' => 'organism__type_id',
-        'field_type' => 'chado_organism__type_id',
-        'widget_type' => 'chado_organism__type_id_widget',
-        'description' => 'Select an Infraspecific Type.',
-        'label' => 'Infrapsecific Type',
-        'is_required' => 0,
-        'storage' => 'field_chado_storage',
-        'widget_settings' => array(
-          'display_label' => 1
+      return TRUE;
+    }
+    return FALSE;
+  }
+  /**
+   * @see TripalField::create_info()
+   */
+  function create_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => 'organism__type_id',
+      'type' => 'chado_organism__type_id',
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+      'settings' => array(
+        'chado_table' => 'organism',
+        'chado_column' => 'type_id',
+        'semantic_web' => 'local:infraspecific_type',
+      ),
+    );
+  }
+  /**
+   * @see TripalField::create_instance_info()
+   */
+  function create_instance_info($entity_type, $bundle, $details) {
+    if (!$this->can_attach($entity_type, $bundle, $details)) {
+      return;
+    }
+
+    $table_name = $details['chado_table'];
+    $type_table = $details['chado_type_table'];
+    $type_field = $details['chado_type_column'];
+    $cv_id      = $details['chado_cv_id'];
+    $cvterm_id  = $details['chado_cvterm_id'];
+
+    return array(
+      'field_name' => 'organism__type_id',
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Infrapsecific Type',
+      'description' => 'The Infrapsecific Type.',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'chado_organism__type_id_widget',
+        'settings' => array(
+          'display_label' => 1,
         ),
-        'field_settings' => array(
-          'chado_table' => 'organism',
-          'chado_column' => 'type_id',
-          'semantic_web' => 'local:infraspecific_type',
+      ),
+      'display' => array(
+        'deafult' => array(
+          'label' => 'above',
+          'type' => 'chado_organism__type_id_formatter',
+          'settings' => array(),
         ),
-      );
-    }
-    return $field_info;
+      ),
+    );
   }
 
   /**

+ 0 - 4
tripal_chado/includes/tripal_chado.field_storage.inc

@@ -313,10 +313,6 @@ function tripal_chado_field_storage_load($entity_type, $entities, $age,
             $field_obj->load($field, $entity, array('record' => $record));
           }
         }
-
-        if (function_exists($load_function)) {
-          $load_function($field, $entity, $base_table, $record);
-        }
       }
 
     } // end: foreach ($fields as $field_id => $ids) {

+ 534 - 518
tripal_chado/includes/tripal_chado.fields.inc

@@ -25,20 +25,539 @@ function tripal_chado_field_info() {
   foreach ($field_files as $file) {
     $field_type = $file->name;
     module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
-
     if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
       $field_obj = new $field_type();
       $info[$field_type] = $field_obj->field_info();
     }
+  }
+  return $info;
+
+}
+
+/**
+ * Implements hook_field_create_info().
+ *
+ * This is a Tripal defined hook that supports integration with the
+ * TripalEntity field.
+ */
+function tripal_chado_field_create_info($entity_type, $bundle, $term) {
+
+  $bundle_name = $bundle->name;
+
+  // The details array is used to pass to the TripalEntity->create_info()
+  // function to provide more details about how the bundle is used by this
+  // module.
+  $details = array();
 
-    $function = $field_type . '_info';
-    if (function_exists($function)) {
-      $info[$field_type] = $function();
+  // This array will hold details that map the bundle to tables in Chado.
+  $bundle_data = array();
+
+  // Get the cvterm that corresponds to this TripalTerm object.
+  $vocab = entity_load('TripalVocab', array($term->vocab_id));
+  $vocab = reset($vocab);
+  $match = array(
+    'dbxref_id' => array(
+      'db_id' => array(
+        'name' => $vocab->vocabulary,
+      ),
+      'accession' => $term->accession
+    ),
+  );
+  $cvterm = chado_generate_var('cvterm', $match);
+
+  // The organism table does not have a type_id so we won't ever find
+  // a record for it in the tripal_cv_defaults table.
+  if ($cvterm->name == 'organism') {
+    $details = array(
+      'chado_cv_id' => $cvterm->cv_id->cv_id,
+      'chado_cvterm_id' => $cvterm->cvterm_id,
+      'chado_table' => 'organism',
+      'chado_type_table' => 'organism',
+      'chado_type_column' =>  '',
+    );
+  }
+  // The analysis table does not have a type_id so we won't ever find
+  // a record for it in the tripalcv_defaults table.
+  else if ($cvterm->name == 'analysis') {
+    $details = array(
+      'chado_cv_id' => $cvterm->cv_id->cv_id,
+      'chado_cvterm_id' => $cvterm->cvterm_id,
+      'chado_table' => 'analysis',
+      'chado_type_table' => 'analysis',
+      'chado_type_column' =>  '',
+    );
+  }
+  else if ($cvterm->name == 'project') {
+    $details = array(
+      'chado_cv_id' => $cvterm->cv_id->cv_id,
+      'chado_cvterm_id' => $cvterm->cvterm_id,
+      'chado_table' => 'project',
+      'chado_type_table' => 'project',
+      'chado_type_column' =>  '',
+    );
+  }
+  else {
+    // TODO: WHAT TO DO IF A VOCABULARY IS USED AS A DEFAULT FOR MULTIPLE
+    // TABLES.
+    // Look to see if this vocabulary is used as a default for any table.
+      $default = db_select('tripal_cv_defaults', 't')
+      ->fields('t')
+      ->condition('cv_id', $cvterm->cv_id->cv_id)
+      ->execute()
+      ->fetchObject();
+    if ($default) {
+      $details = array(
+        'chado_cv_id' => $cvterm->cv_id->cv_id,
+        'chado_cvterm_id' => $cvterm->cvterm_id,
+        'chado_table' => $default->table_name,
+        'chado_type_table' => $default->table_name,
+        'chado_type_column' =>  $default->field_name,
+      );
+    }
+  }
+
+  // Save the mapping information so that we can reuse it when we need to
+  // look things up for later (such as the hook_create_instance_info() function.
+  tripal_set_bundle_variable('chado_cv_id', $bundle->id, $details['chado_cv_id']);
+  tripal_set_bundle_variable('chado_cvterm_id', $bundle->id, $details['chado_cvterm_id']);
+  tripal_set_bundle_variable('chado_table', $bundle->id, $details['chado_table']);
+  tripal_set_bundle_variable('chado_type_table', $bundle->id, $details['chado_type_table']);
+  tripal_set_bundle_variable('chado_type_column', $bundle->id, $details['chado_type_column']);
+
+  $base_fields = tripal_chado_field_create_base('create_info', $entity_type, $bundle, $details);
+  $custom_fields = tripal_chado_field_create_info_custom($entity_type, $bundle, $details);
+  return array_merge($base_fields, $custom_fields);
+}
+
+/**
+ * A helper function for the tripal_chado_field_create_info() function.
+ *
+ * This function adds in the custom fields info by instantiating the class
+ * for the custom field, calling the create_info() function and
+ * returning the info array.
+ *
+ * @param $entity_type
+ *   The type of entity (e.g TripalEntity)
+ * @param $bundle
+ *   The bundle object.
+ * @param $details
+ *   An array containing the mapping of the bundle to the Chado table.
+ */
+function tripal_chado_field_create_info_custom($entity_type, $bundle, $details) {
+  $info = array();
+
+  // Find all of the files in the tripal_chado/includes/fields directory.
+  $fields_path = drupal_get_path('module', 'tripal_chado') . '/includes/fields';
+  $field_files = file_scan_directory($fields_path, '/^chado_.*\.inc$/');
+
+  // Iterate through the fields, include the file and run the info function.
+  foreach ($field_files as $file) {
+    $field_type = $file->name;
+    module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
+    if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
+      $field_obj = new $field_type();
+      $result = $field_obj->create_info($entity_type, $bundle, $details);
+      if (is_array($result)) {
+        $info[$result['field_name']] = $result;
+      }
     }
   }
   return $info;
+}
+
+/**
+ * Retrieves either the create_info or create_instance_info arrays.
+ *
+ * The logic for creating the fields for the base table is so similar for
+ * both the create_info and create_instance_info arrays they are both
+ * handled by this function to prevent duplication of code.
+ *
+ * @param $step
+ *   Set to 'create_info' to retrun the create_info array or
+ *   'create_instance_info' to return the create_instance_info array.
+ * @param $entity_type
+ *   The type of entity (e.g TripalEntity)
+ * @param $bundle
+ *   The bundle object.
+ * @param $details
+ *   An array containing the mapping of the bundle to the Chado table.
+ *
+ * @return
+ *   An array compabile with the tripal_chado_field_create_info() and
+ *   tripal_chado_field_create_instance_info() functions.
+ */
+function tripal_chado_field_create_base($step, $entity_type, $bundle, $details) {
+  $table_name = $details['chado_table'];
+  $type_table = $details['chado_type_table'];
+  $type_field = $details['chado_type_column'];
+
+  // Iterate through the columns of the table and see if fields have been
+  // created for each one. If not, then create them.
+  $schema = chado_get_schema($table_name);
+  $columns = $schema['fields'];
+  $fields = array();
+  foreach ($columns as $column_name => $details) {
+    $field_name = $table_name . '__' . $column_name;
+
+    // Skip the primary key field.
+    if ($column_name == $schema['primary key'][0]) {
+      continue;
+    }
 
+    // Skip the type field.
+    if ($table_name == $type_table and $column_name == $type_field) {
+      continue;
+    }
+
+    // Get the field defaults for this column.
+    $field_info = array();
+    if ($step == 'create_info') {
+      $field_info = tripal_chado_field_create_info_base_defaults($field_name,
+        $table_name, $schema, $column_name);
+    }
+    if ($step == 'create_instance_info') {
+      $field_info = tripal_chado_field_create_instance_info_base_defaults($bundle->name,
+        $field_name, $table_name, $schema, $column_name);
+    }
+
+    // TODO: add in a call to drupal_alter to allow other modules to change
+    // the field settings.
+
+    // Add the field to the bundle.
+    $fields[$field_name] = $field_info;
+  }
+  return $fields;
 }
+/**
+ * A helper function for the tripal_chado_field_create_info() function.
+ *
+ * This function generates the default chado_info array for a column in
+ * a base table of Chado.  All of fields returned by this function use
+ * default Drupal fields to manage the data in Chado columns.  For
+ * custom handling of columns there are custom TripalEntity extensions that
+ * are added by the tripal_chado_field_create_info_custom() function.  A
+ * custom field will superceed any default base field of the same name
+ * provided here.
+ *
+ * @param $field_name
+ *   The name for the new field.
+ * @param $table_name
+ *   The Chado table
+ * @param $schema
+ *   The Drupal schema array for the Chado table.
+ * @param $column_name
+ *   The name of the column in the Chado table.
+ * @return
+ *   An associative array compatible with the tripal_chado_field_create_info()
+ *   function.
+ */
+function tripal_chado_field_create_info_base_defaults($field_name, $table_name,
+    $schema, $column_name) {
+
+  $details = $schema['fields'][$column_name];
+
+  // Set some defaults for the field.
+  $field = array(
+    'field_name' => $field_name,
+    'type' => '',
+    'cardinality' => 1,
+    'locked' => FALSE,
+    'storage' => array(
+      'type' => 'field_chado_storage',
+    ),
+    'settings' => array(
+      'chado_table' => $table_name,
+      'chado_column' => $column_name,
+      'semantic_web' => '',
+    ),
+  );
+
+  // Alter the field info array depending on the column details.
+  switch($details['type']) {
+    case 'char':
+      $field['type'] = 'text';
+      $field['settings']['max_length'] = $details['length'];
+      break;
+    case 'varchar':
+      $field['type'] = 'text';
+      $field['settings']['max_length'] = $details['length'];
+      break;
+    case 'text':
+      $field['type'] = 'text';
+      $field['settings']['max_length'] = 17179869184;
+      $field['settings']['text_processing'] = 1;
+      break;
+    case 'blob':
+      // not sure how to support a blob field.
+      continue;
+      break;
+    case 'int':
+      $field['type'] = 'number_integer';
+      break;
+    case 'float':
+      $field['type'] = 'number_float';
+      $field['settings']['precision'] = 10;
+      $field['settings']['scale'] = 2;
+      $field['settings']['decimal_separator'] = '.';
+      break;
+    case 'numeric':
+      $field['type'] = 'number_decimal';
+      break;
+    case 'serial':
+      // Serial fields are most likely not needed as a field.
+      break;
+    case 'boolean':
+      $field['type'] = 'list_boolean';
+      $field['settings']['allowed_values'] = array(0 => "No", 1 => "Yes");
+      break;
+    case 'datetime':
+      // Use the Drupal Date and Date API to create the field/widget
+      $field['type'] = 'datetime';
+      break;
+  }
+
+  // Set some default semantic web information
+  if ($column_name == 'uniquename') {
+    $field['settings']['text_processing'] = 0;
+  }
+  //
+  // PUB TABLE
+  //
+  elseif ($table_name == 'pub' and $column_name == 'uniquename') {
+    $field['type'] = 'text';
+    $field['settings']['text_processing'] = 0;
+  }
+
+  //
+  // ANALYSIS TABLE
+  //
+  elseif ($table_name == 'analysis' and $column_name == 'sourceuri') {
+    $field['type'] = 'text';
+    $field['settings']['text_processing'] = 0;
+  }
+
+  return $field;
+}
+
+/**
+ * Implements hook_field_create_instance_info().
+ *
+ * This is a Tripal defined hook that supports integration with the
+ * TripalEntity field.
+ */
+function tripal_chado_field_create_instance_info($entity_type, $bundle, $term) {
+
+  // Get the details about the mapping of this bundle to the Chado table:
+  $details = array(
+    'chado_cv_id' => tripal_get_bundle_variable('chado_cv_id', $bundle->id),
+    'chado_cvterm_id' => tripal_get_bundle_variable('chado_cvterm_id', $bundle->id),
+    'chado_table' => tripal_get_bundle_variable('chado_table', $bundle->id),
+    'chado_type_table' => tripal_get_bundle_variable('chado_type_table', $bundle->id),
+    'chado_type_column' => tripal_get_bundle_variable('chado_type_column', $bundle->id),
+  );
+
+  $base_fields = tripal_chado_field_create_base('create_instance_info', $entity_type, $bundle, $details);
+  $custom_fields = tripal_chado_field_create_instance_info_custom($entity_type, $bundle, $details);
+  return array_merge($base_fields, $custom_fields);
+
+}
+/**
+ * A helper function for the tripal_chado_field_create_instance_info() function.
+ *
+ * This function generates the default chado_instance_info array for a column in
+ * a base table of Chado.  All of fields returned by this function use
+ * default Drupal fields to manage the data in Chado columns.  For
+ * custom handling of columns there are custom TripalEntity extensions that
+ * are added by the tripal_chado_field_create_info_custom() function.  A
+ * custom field will superceed any default base field of the same name
+ * provided here.
+ *
+ * @param $bundle_name
+ *   The name of the bundle to which this field will be attached.
+ * @param $field_name
+ *   The name for the new field.
+ * @param $table_name
+ *   The Chado table
+ * @param $schema
+ *   The Drupal schema array for the Chado table.
+ * @param $column_name
+ *   The name of the column in the Chado table.
+ * @return
+ *   An associative array compatible with the tripal_chado_field_create_info()
+ *   function.
+ */
+function tripal_chado_field_create_instance_info_base_defaults($bundle_name,
+    $field_name, $table_name, $schema, $column_name) {
+
+  $details = $schema['fields'][$column_name];
+
+  $field =  array(
+      'field_name' => $field_name,
+      'entity_type' => 'TripalEntity',
+      'bundle' => $bundle_name,
+      'label' => ucwords(preg_replace('/_/', ' ', $column_name)),
+      'description' => '',
+      'required' => FALSE,
+      'settings' => array(),
+      'widget' => array(
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'default' => array(
+          'label' => 'above',
+          'settings' => array(),
+        ),
+      ),
+    );
+
+  // Determine if the field is required.
+  if (array_key_exists('not null', $details) and $details['not null'] === TRUE) {
+    $field_info['required'] = TRUE;
+  }
+
+  // Alter the field info array depending on the column details.
+  switch($details['type']) {
+    case 'char':
+      $field['widget']['type'] = 'text_textfield';
+      break;
+    case 'varchar':
+      $field['widget']['type'] = 'text_textfield';
+      break;
+    case 'text':
+      $field['widget']['type'] = 'text_textarea';
+      $field['widget']['settings']['format'] = filter_default_format();
+      break;
+    case 'blob':
+      // not sure how to support a blob field.
+      continue;
+      break;
+    case 'int':
+      $field['widget']['type'] = 'number';
+      break;
+    case 'float':
+      $field['widget']['type'] = 'number';
+      break;
+    case 'numeric':
+      $field['widget']['type'] = 'number';
+      break;
+    case 'serial':
+      // Serial fields are most likely not needed as a field.
+      break;
+    case 'boolean':
+      $field['widget']['type'] = 'options_onoff';
+      break;
+    case 'datetime':
+      $field['widget']['type'] = 'date_select';
+      $field['widget']['settings']['increment'] = 1;
+      $field['widget']['settings']['tz_handling'] = 'none';
+      $field['widget']['settings']['collapsible'] = TRUE;
+
+      // TODO: Add settings so that the minutes increment by 1.
+      // And turn off the timezone, as the Chado field doesn't support it.
+      break;
+  }
+
+  // Set some default semantic web information
+  if ($column_name == 'uniquename') {
+    $field['widget_type'] = 'text_textfield';
+  }
+  elseif ($field['label'] == 'Timeaccessioned') {
+    $field['label'] = 'Time Accessioned';
+    $field['description'] = 'Please enter the time that this record was first added to the database.';
+  }
+  elseif ($field['label'] == 'Timelastmodified') {
+    $field['label'] = 'Time Last Modified';
+    $field['description'] = 'Please enter the time that this record was last modified. The default is the current time.';
+  }
+  //
+  // ORGANISM TABLE
+  //
+  elseif ($table_name == 'organism' and $column_name == 'comment') {
+    $field['label'] = 'Description';
+  }
+  //
+  // PUB TABLE
+  //
+  elseif ($table_name == 'pub' and $column_name == 'uniquename') {
+    $field['widget_type'] = 'text_textfield';
+  }
+
+  //
+  // ANALYSIS TABLE
+  //
+  elseif ($table_name == 'analysis' and $column_name == 'program') {
+    $field['description'] = 'The program name (e.g. blastx, blastp, sim4, genscan. If the analysis was not derived from a software package then provide a very brief description of the pipeline, workflow or method.';
+    $field['label'] = 'Program, Pipeline, Workflow or Method Name.';
+  }
+  elseif ($table_name == 'analysis' and $column_name == 'sourceuri') {
+    $field['widget_type'] = 'text_textfield';
+    $field['label'] = 'Source URL';
+    $field['description'] = 'The URL where the original source data was derived.  Ideally, this should link to the page where more information about the source data can be found.';
+  }
+  elseif ($table_name == 'analysis' and $column_name == 'sourcename') {
+    $field['label'] = 'Source Name';
+    $field['description'] = 'The name of the source data. This could be a file name, data set or a small description for how the data was collected. For long descriptions use the larger description field.';
+  }
+  elseif ($table_name == 'analysis' and $column_name == 'sourceversion') {
+    $field['label'] = 'Source Version';
+    $field['description'] = 'If hte source data set has a version include it here.';
+  }
+  elseif ($table_name == 'analysis' and $column_name == 'algorithm') {
+    $field['label'] = 'Source Version';
+    $field['description'] = 'The name of the algorithm used to produce the dataset if different from the program.';
+  }
+  elseif ($table_name == 'analysis' and $column_name == 'programversion') {
+    $field['label'] = 'Program Version';
+    $field['description'] = 'The version of the program used to perform this analysis. (e.g. TBLASTX 2.0MP-WashU [09-Nov-2000]. Enter "n/a" if no version is available or applicable.';
+  }
+  //
+  // PROJECT TABLE
+  //
+  elseif ($table_name == 'project' and $column_name == 'description') {
+    $field['label'] = 'Short Description';
+  }
+
+  return $field;
+}
+
+/**
+ * A helper function for the tripal_chado_field_create_instance_info() function.
+ *
+ * This function adds in the custom fields info by instantiating the class
+ * for the custom field, calling the create_instance_info() function and
+ * returning the info array.
+ *
+ * @param $entity_type
+ *   The type of entity (e.g TripalEntity)
+ * @param $bundle
+ *   The bundle object.
+ * @param $details
+ *   An array containing the mapping of the bundle to the Chado table.
+ */
+function tripal_chado_field_create_instance_info_custom($entity_type, $bundle, $details) {
+  $info = array();
+
+  // Find all of the files in the tripal_chado/includes/fields directory.
+  $fields_path = drupal_get_path('module', 'tripal_chado') . '/includes/fields';
+  $field_files = file_scan_directory($fields_path, '/^chado_.*\.inc$/');
+
+  // Iterate through the fields, include the file and run the info function.
+  foreach ($field_files as $file) {
+    $field_type = $file->name;
+    module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
+    if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
+      $field_obj = new $field_type();
+      $result = $field_obj->create_instance_info($entity_type, $bundle, $details);
+      if (is_array($result)) {
+        $info[$result['field_name']] = $result;
+      }
+    }
+  }
+  return $info;
+}
+
 /**
  * Implements hook_field_widget_info().
  *
@@ -55,16 +574,10 @@ function tripal_chado_field_widget_info() {
     $field_type = $field['type'];
     if ($field['storage']['type'] == 'field_chado_storage') {
       module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
-
       if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
         $field_obj = new $field_type();
         $widgets[$field_type . '_widget'] = $field_obj->widget_info();
       }
-
-      $function = $field_type . '_widget_info';
-      if (function_exists($function)) {
-        $widgets[$field_type . '_widget'] = $function();
-      }
     }
   }
   return $widgets;
@@ -85,16 +598,10 @@ function tripal_chado_field_formatter_info() {
     $field_type = $field['type'];
     if ($field['storage']['type'] == 'field_chado_storage') {
       module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
-
       if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
         $field_obj = new $field_type();
         $formatters[$field_type . '_formatter'] = $field_obj->formatter_info();
       }
-
-      $function = $field_type . '_formatter_info';
-      if (function_exists($function)) {
-        $formatters[$field_type . '_formatter'] = $function();
-      }
     }
   }
   return $formatters;
@@ -112,12 +619,6 @@ function tripal_chado_field_settings_form($field, $instance, $has_data) {
     $field_obj = new $field_type();
     $form = $field_obj->settings_form($field, $instance, $has_data);
   }
-
-  $function = $field_type . '_settings_form';
-  if (function_exists($function)) {
-    $form = $function($field, $instance, $has_data);
-  }
-
   return $form;
 }
 /**
@@ -133,12 +634,6 @@ function tripal_chado_field_formatter_settings_summary($field, $instance, $view_
     $field = new $field_type();
     $summary = $field->formatter_settings_summary($field, $instance, $view_mode);
   }
-
-  $function = $field_type . '_formatter_settings_summary';
-  if (function_exists($function)) {
-    $summary = $function($field, $instance, $view_mode);
-  }
-
   return $summary;
 }
 
@@ -183,11 +678,6 @@ function tripal_chado_field_formatter_view($entity_type, $entity, $field,
     $field_obj->formatter_view($element, $entity_type, $entity, $field, $instance, $langcode, $items, $display);
   }
 
-  $function = $display['type'];
-  if (function_exists($function)) {
-    $function($element, $entity_type, $entity, $field, $instance, $langcode, $items, $display);
-  }
-
   return $element;
 }
 
@@ -199,98 +689,20 @@ function tripal_chado_field_widget_form(&$form, &$form_state, $field,
 
   $widget = $element;
 
-  $field_name = $instance['field_name'];
-  $field_type = $field['type'];
-  form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/' . $field_type);
-  module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_name);
-
-  if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
-    $field_obj = new $field_type();
-    $field_obj->widget_form($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-  }
-
-  $function = $field_type . '_widget';
-  if (function_exists($function)) {
-    $function($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-  }
-
-  return $widget;
-}
-
-/**
- * Returns the values of the field from the $form_state.
- */
-function tripal_chado_get_field_form_values($field_name, $form_state, $delta = 0, $child = NULL) {
-  $value = NULL;
-  // The form_state must have the 'values' key. If not then just return.
-  if (!array_key_exists('values', $form_state)) {
-    return $value;
-  }
-
-  // If the field name is not in the form_state['values'] then return.
-  if (!array_key_exists($field_name, $form_state['values'])) {
-    return $value;
-  }
-
-  // Iterate through the values looking for the field_name provided.
-  foreach ($form_state['values'][$field_name] as $langcode => $items) {
-    if (!array_key_exists($delta, $items)) {
-      continue;
-    }
-    $item = $items[$delta];
-    if ($child){
-      if(array_key_exists($child, $item) and $item[$child] != '') {
-        $value = $item[$child];
-      }
-    }
-    else {
-      $value = $item['value'];
-    }
-  }
-  return $value;
-}
-
-/**
- * Sets the values of the field from the $form_state.  If no child
- * argument is specified then the 'value' field is set.
- *
- * @param $field_name
- *   The name of the field to set.
- * @param $form_state
- *   The form's form_state array.
- * @param $newvalue
- *   The new value to set for the field.
- * @param $delta
- *   If cardinality of a field is greater than 1 the delta indicates
- *   which instance to set.
- * @param $child
- *   The name of the property to set iff other than 'value'.
- *
- * @return
- *   TRUE if the value was set, FALSE otherwise.
- */
-function tripal_chado_set_field_form_values($field_name, &$form_state, $newvalue, $delta = 0, $child = NULL) {
-  // The form_state must have the 'values' key. If not then just return.
-  if (!array_key_exists('values', $form_state)) {
-    return FALSE;
-  }
-
-  // If the field name is not in the form_state['values'] then reutrn.
-  if (!array_key_exists($field_name, $form_state['values'])) {
-    return FALSE;
-  }
+  $field_name = $instance['field_name'];
+  $field_type = $field['type'];
+  form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/' . $field_type);
+  module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_name);
 
-  foreach ($form_state['values'][$field_name] as $langcode => $items) {
-    if ($child) {
-      $form_state['values'][$field_name][$langcode][$delta][$child] = $newvalue;
-    }
-    else {
-      $form_state['values'][$field_name][$langcode][$delta]['value'] = $newvalue;
-    }
+  if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
+    $field_obj = new $field_type();
+    $field_obj->widget_form($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
   }
-  return TRUE;
+
+  return $widget;
 }
 
+
 /**
  * Implements hook_field_widget_form_alter().
  */
@@ -359,159 +771,7 @@ function tripal_chado_field_submit($entity_type, $entity, $field, $instance,
   }
 }
 
-/**
- * Returns a $field_info array for a field based on a database column.
- *
- */
-function tripal_chado_get_bundle_fields_base__fields_defaults($table_name, $schema, $column_name) {
-  $details = $schema['fields'][$column_name];
-
-  // Create an array with information about this field.
-  $field = array(
-    'field_type' => '',
-    'widget_type' => '',
-    'description' => '',
-    'label' => ucwords(preg_replace('/_/', ' ', $column_name)),
-    'is_required' => 0,
-    'storage' => 'field_chado_storage',
-    'widget_settings' => array(
-      'display_label' => 1
-    ),
-    'field_settings' => array(
-      // The table in Chado where this field maps to.
-      'chado_table' => $table_name,
-      // The column in the Chado table that this field maps to.
-      'chado_column' => $column_name,
-      'semantic_web' => '',
-    ),
-  );
-
-  // Alter the field info array depending on the column details.
-  switch($details['type']) {
-    case 'char':
-      $field['field_type'] = 'text';
-      $field['widget_type'] = 'text_textfield';
-      $field['field_settings']['max_length'] = $details['length'];
-      break;
-    case 'varchar':
-      $field['field_type'] = 'text';
-      $field['widget_type'] = 'text_textfield';
-      $field['field_settings']['max_length'] = $details['length'];
-      break;
-    case 'text':
-      $field['field_type'] = 'text';
-      $field['widget_type'] = 'text_textarea';
-      $field['field_settings']['max_length'] = 17179869184;
-      $field['field_settings']['text_processing'] = 1;
-      $field['format'] = filter_default_format();
-      break;
-    case 'blob':
-      // not sure how to support a blob field.
-      continue;
-      break;
-    case 'int':
-      $field['field_type'] = 'number_integer';
-      $field['widget_type'] = 'number';
-      break;
-    case 'float':
-      $field['field_type'] = 'number_float';
-      $field['widget_type'] = 'number';
-      $field['field_settings']['precision'] = 10;
-      $field['field_settings']['scale'] = 2;
-      $field['field_settings']['decimal_separator'] = '.';
-      break;
-    case 'numeric':
-      $field['field_type'] = 'number_decimal';
-      $field['widget_type'] = 'number';
-      break;
-    case 'serial':
-      // Serial fields are most likely not needed as a field.
-      break;
-    case 'boolean':
-      $field['field_type'] = 'list_boolean';
-      $field['widget_type'] = 'options_onoff';
-      $field['field_settings']['allowed_values'] = array(0 => "No", 1 => "Yes");
-      break;
-    case 'datetime':
-      // Use the Drupal Date and Date API to create the field/widget
-      $field['field_type'] = 'datetime';
-      $field['widget_type'] = 'date_select';
-      $field['widget_settings']['increment'] = 1;
-      $field['widget_settings']['tz_handling'] = 'none';
-      $field['widget_settings']['collapsible'] = TRUE;
-
-      // TODO: Add settings so that the minutes increment by 1.
-      // And turn off the timezone, as the Chado field doesn't support it.
-      break;
-  }
-
-  // Set some default semantic web information
-  if ($column_name == 'uniquename') {
-    $field['widget_type'] = 'text_textfield';
-    $field['field_settings']['text_processing'] = 0;
-  }
-  elseif ($field['label'] == 'Timeaccessioned') {
-    $field['label'] = 'Time Accessioned';
-    $field['description'] = 'Please enter the time that this record was first added to the database.';
-  }
-  elseif ($field['label'] == 'Timelastmodified') {
-    $field['label'] = 'Time Last Modified';
-    $field['description'] = 'Please enter the time that this record was last modified. The default is the current time.';
-  }
-  //
-  // ORGANISM TABLE
-  //
-  elseif ($field['field_settings']['chado_table'] == 'organism' and $field['field_settings']['chado_column'] == 'comment') {
-    $field['label'] = 'Description';
-  }
-  //
-  // PUB TABLE
-  //
-  elseif ($field['field_settings']['chado_table'] == 'pub' and $field['field_settings']['chado_column'] == 'uniquename') {
-    $field['field_type'] = 'text';
-    $field['widget_type'] = 'text_textfield';
-    $field['field_settings']['text_processing'] = 0;
-  }
-
-  //
-  // ANALYSIS TABLE
-  //
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'program') {
-    $field['description'] = 'The program name (e.g. blastx, blastp, sim4, genscan. If the analysis was not derived from a software package then provide a very brief description of the pipeline, workflow or method.';
-    $field['label'] = 'Program, Pipeline, Workflow or Method Name.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourceuri') {
-    $field['field_type'] = 'text';
-    $field['widget_type'] = 'text_textfield';
-    $field['field_settings']['text_processing'] = 0;
-    $field['label'] = 'Source URL';
-    $field['description'] = 'The URL where the original source data was derived.  Ideally, this should link to the page where more information about the source data can be found.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourcename') {
-    $field['label'] = 'Source Name';
-    $field['description'] = 'The name of the source data. This could be a file name, data set or a small description for how the data was collected. For long descriptions use the larger description field.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourceversion') {
-    $field['label'] = 'Source Version';
-    $field['description'] = 'If hte source data set has a version include it here.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'algorithm') {
-    $field['label'] = 'Source Version';
-    $field['description'] = 'The name of the algorithm used to produce the dataset if different from the program.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'programversion') {
-    $field['label'] = 'Program Version';
-    $field['description'] = 'The version of the program used to perform this analysis. (e.g. TBLASTX 2.0MP-WashU [09-Nov-2000]. Enter "n/a" if no version is available or applicable.';
-  }
-  //
-  // PROJECT TABLE
-  //
-  elseif ($field['field_settings']['chado_table'] == 'project' and $field['field_settings']['chado_column'] == 'description') {
-    $field['label'] = 'Short Description';
-  }
 
-  return $field;
-}
 
 /**
  * Implements hook_form_FORM_ID_alter().
@@ -546,6 +806,7 @@ function tripal_chado_form_field_ui_display_overview_form_alter(&$form, &$form_s
  * for users to show or manage.
  */
 function tripal_chado_form_field_ui_field_overview_form_alter(&$form, &$form_state, $form_id) {
+
   // Remove the kvproperty_addr field as it isn't ever displayed. It's just used
   // on the add/edit form of an entity for adding new property fields.
   $fields_names = element_children($form['fields']);
@@ -583,251 +844,6 @@ function tripal_chado_field_is_empty($item, $field) {
   return TRUE;
 }
 
-/**
- * Implements hook_update_bundle_fields().
- *
- */
-function tripal_chado_update_bundle_fields($entity_type, $bundle, $term) {
-  // Get the list of fields that should be attached to this bundle and
-  // add them.
-  $bundle_name = $bundle->name;
-  $fields = tripal_chado_get_bundle_fields($entity_type, $bundle, $term);
-  foreach ($fields as $field_name => $field_info) {
-    tripal_update_bundle_field($field_name, $field_info, $entity_type, $bundle_name);
-  }
-}
-
-/**
- * Implements hook_add_bundle_fields().
- */
-function tripal_chado_add_bundle_fields($entity_type, $bundle, $term) {
-
-  // Get the list of fields that should be attached to this bundle and
-  // add them.
-  $bundle_name = $bundle->name;
-  $fields = tripal_chado_get_bundle_fields($entity_type, $bundle, $term);
-  foreach ($fields as $field_name => $field_info) {
-    tripal_add_bundle_field($field_name, $field_info, $entity_type, $bundle_name);
-  }
-}
-/**
- * Retreives a list of the fields that should be attached to the bundle.
- *
- * @return
- *   An associative array of fields to attach to the bundle. The keys are the
- *   field names and the values is an info array that can be passed to the
- *   tripal_add_bundle_field() function.
- */
-function tripal_chado_get_bundle_fields($entity_type, $bundle, $term) {
-
-  $fields = array();
-
-  $bundle_name = $bundle->name;
-
-  // This array will hold details that map the bundle to tables in Chado.
-  $bundle_data = array();
-
-  // Get the cvterm that corresponds to this TripalTerm object.
-  $vocab = entity_load('TripalVocab', array($term->vocab_id));
-  $vocab = reset($vocab);
-  $match = array(
-    'dbxref_id' => array(
-      'db_id' => array(
-        'name' => $vocab->vocabulary,
-      ),
-      'accession' => $term->accession
-    ),
-  );
-  $cvterm = chado_generate_var('cvterm', $match);
-
-  // The organism table does not have a type_id so we won't ever find
-  // a record for it in the tripal_cv_defaults table.
-  if ($cvterm->name == 'organism') {
-    $bundle_data = array(
-      'cv_id' => $cvterm->cv_id->cv_id,
-      'cvterm_id' => $cvterm->cvterm_id,
-      'data_table' => 'organism',
-      'type_table' => 'organism',
-      'field' =>  '',
-    );
-  }
-  // The analysis table does not have a type_id so we won't ever find
-  // a record for it in the tripalcv_defaults table.
-  else if ($cvterm->name == 'analysis') {
-    $bundle_data = array(
-      'cv_id' => $cvterm->cv_id->cv_id,
-      'cvterm_id' => $cvterm->cvterm_id,
-      'data_table' => 'analysis',
-      'type_table' => 'analysis',
-      'field' =>  '',
-    );
-  }
-  else if ($cvterm->name == 'project') {
-    $bundle_data = array(
-      'cv_id' => $cvterm->cv_id->cv_id,
-      'cvterm_id' => $cvterm->cvterm_id,
-      'data_table' => 'project',
-      'type_table' => 'project',
-      'field' =>  '',
-    );
-  }
-  else {
-    // TODO: WHAT TO DO IF A VOCABULARY IS USED AS A DEFAULT FOR MULTIPLE
-    // TABLES.
-    // Look to see if this vocabulary is used as a default for any table.
-    $default = db_select('tripal_cv_defaults', 't')
-      ->fields('t')
-      ->condition('cv_id', $cvterm->cv_id->cv_id)
-      ->execute()
-      ->fetchObject();
-    if ($default) {
-      $bundle_data = array(
-        'cv_id' => $cvterm->cv_id->cv_id,
-        'cvterm_id' => $cvterm->cvterm_id,
-        'data_table' => $default->table_name,
-        'type_table' => $default->table_name,
-        'field' =>  $default->field_name,
-      );
-    }
-  }
-
-  // Save the mapping information so that we can reuse it when we need to
-  // look things up for later for an entity
-  tripal_set_bundle_variable('chado_cvterm_id', $bundle->id, $bundle_data['cvterm_id']);
-  tripal_set_bundle_variable('chado_table', $bundle->id, $bundle_data['data_table']);
-  tripal_set_bundle_variable('chado_column', $bundle->id, $bundle_data['field']);
-
-  // Find all of the files in the tripal_chado/includes/fields directory.
-  $fields_path = drupal_get_path('module', 'tripal_chado') . '/includes/fields';
-  $field_files = file_scan_directory($fields_path, '/^chado_.*\.inc$/');
-
-  // Add fields from the base table.
-  tripal_chado_get_bundle_fields_base__fields($fields, $entity_type, $bundle_name, $bundle_data);
-
-  // Iterate through the fields, include the file and run the info function.
-  foreach ($field_files as $file) {
-    $field_type = $file->name;
-    module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
-
-    if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
-      $field_obj = new $field_type();
-      $field_info = $field_obj->attach_info($entity_type, $bundle, $bundle_data);
-    }
-
-    $function = $field_type . '_attach_info';
-    if (function_exists($function)) {
-      $field_info = $function($entity_type, $bundle, $bundle_data);
-    }
-
-    if (!is_array($field_info) or count(array_keys($field_info)) == 0) {
-      continue;
-    }
-    $field_name = $field_info['field_name'];
-
-    $fields[$field_name] = $field_info;
-  }
-
-  // Add in the semantic web details
-  foreach ($fields as $field_name => $field) {
-    if (!array_key_exists('chado_table', $field['field_settings'])) {
-      continue;
-    }
-    $chado_column = $field['field_settings']['chado_column'];
-    $chado_table = $field['field_settings']['chado_table'];
-
-    // Get the semantic web mapping for this field. First look for a
-    // table specific mapping.
-    $smweb = db_select('chado_semweb', 'CS')
-      ->fields('CS')
-      ->condition('chado_column', $chado_column)
-      ->condition('chado_table', $chado_table)
-      ->execute()
-      ->fetchObject();
-    // We don't have a table/column specific mapping, so let's look for a
-    // generic column mapping.
-    if (!$smweb) {
-      $smweb = db_select('chado_semweb', 'CS')
-      ->fields('CS')
-      ->condition('chado_column', $chado_column)
-      ->execute()
-      ->fetchObject();
-    }
-    if ($smweb) {
-      $cvterm = tripal_get_cvterm(array('cvterm_id' => $smweb->cvterm_id));
-      $fields[$field_name]['field_settings']['semantic_web'] = $cvterm->dbxref_id->db_id->name . ':' . $cvterm->dbxref_id->accession;
-    }
-  }
-
-  return $fields;
-}
-
-
-/**
- * Adds the fields for the base table to the entity.
- */
-function tripal_chado_get_bundle_fields_base__fields(&$fields, $entity_type_name, $bundle_name, $bundle_data) {
-
-  $table_name = $bundle_data['data_table'];
-  $type_table = $bundle_data['type_table'];
-  $type_field = $bundle_data['field'];
-
-  // Iterate through the columns of the table and see if fields have been
-  // created for each one. If not, then create them.
-  $schema = chado_get_schema($table_name);
-  $columns = $schema['fields'];
-  foreach ($columns as $column_name => $details) {
-    $field_name = $table_name . '__' . $column_name;
-
-    // Skip the primary key field.
-    if ($column_name == $schema['primary key'][0]) {
-      continue;
-    }
-
-    // Skip the type field.
-    if ($table_name == $type_table and $column_name == $type_field) {
-      continue;
-    }
-
-    // Get the field defaults for this column.
-    $field_info = tripal_chado_get_bundle_fields_base__fields_defaults($table_name, $schema, $column_name);
-
-
-    // TODO: add in a call to drupal_alter to allow other modules to change
-    // the field settings.
-
-    // Determine if the field is required.
-    if (array_key_exists('not null', $details) and $details['not null'] === TRUE) {
-      $field_info['is_required'] = array_key_exists('default', $details) ? 0 : 1;
-    }
-
-    // If we don't have a field type then we don't need to create a field.
-    if (!$field_info['field_type']) {
-      // If we don't have a field type but it is required and doesn't have
-      // a default value then we are in trouble.
-      if ($field_info['is_required'] and !array_key_exists('default', $details)) {
-        throw new Exception(t('The %table.%field type, %type, is not yet supported for Entity fields, but it is required,',
-            array('%table' => $table_name, '%field' => $column_name, '%type' => $details['type'])));
-      }
-      continue;
-    }
-
-    // If this field is a foreign key field then we will have a custom field.
-    $is_fk = FALSE;
-    if (array_key_exists('foreign keys', $schema)) {
-      foreach ($schema['foreign keys'] as $remote_table => $fk_details) {
-        if (array_key_exists($column_name, $fk_details['columns'])) {
-          $is_fk = TRUE;
-        }
-      }
-    }
-
-    // Add the field to the bundle.
-    $fields[$field_name] = $field_info;
-  }
-}
-
-
-
 
 
 

+ 11 - 3
tripal_chado/includes/tripal_chado.setup.inc

@@ -390,17 +390,25 @@ function tripal_chado_prepare_chado() {
     // For the TripalBundle entities we will want to associate the cvterm_id,
     // and the chado table and field that it maps to.  We will use a few
     // variables to do this:
+    tripal_insert_variable(
+      'chado_cv_id',
+      'The ID of the controlled vocabulary in the chado.cv table..'
+    );
     tripal_insert_variable(
       'chado_cvterm_id',
-      'The cvterm_id that a TripalBundle maps to.'
+      'The ID of the controlled vocabulary term in the chado.cvterm table.'
     );
     tripal_insert_variable(
       'chado_table',
       'The name of the table to which a TripalBundle maps.'
     );
     tripal_insert_variable(
-      'chado_column',
-      'The name of the column within the table that a TripalBundle maps to.'
+      'chado_type_table',
+      'The table that houses the foreign key the cvterm table.'
+    );
+    tripal_insert_variable(
+      'chado_type_column',
+      'The name of the column within the type table that houses the cvterm.'
     );
 
     // We want to provide a set of commonly used entity types by default. This