Browse Source

Fixing fields... not quite finished.

Stephen Ficklin 8 years ago
parent
commit
568feec8fd

+ 2 - 2
tripal/includes/TripalField.inc

@@ -189,9 +189,9 @@ class TripalField {
   public function widget_form(&$widget, $form, $form_state, $field, $instance,
       $langcode, $items, $delta, $element) {
 
-    $form['value'] = array(
+    $widget['value'] = array(
       '#type' => 'value',
-      '#value' => $items[$delta]['value'],
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
     );
   }
   /**

+ 49 - 66
tripal_chado/includes/fields/chado_base__dbxref_id.inc

@@ -100,6 +100,7 @@ class chado_base__dbxref_id extends TripalField {
    */
   function formatter_view(&$element, $entity_type, $entity, $field,
       $instance, $langcode, $items, $display) {
+
     foreach ($items as $delta => $item) {
       if ($item['value']) {
         $content = $item['value']['namespace'] . ':' . $item['value']['accession'];
@@ -120,8 +121,12 @@ class chado_base__dbxref_id extends TripalField {
       $langcode, $items, $delta, $element) {
 
     $field_name = $field['field_name'];
+    $field_type = $field['type'];
+    $field_table = $field['settings']['chado_table'];
+    $field_column = $field['settings']['chado_column'];
 
     // Get the field defaults.
+    $fk_val = '';
     $dbxref_id = '';
     $db_id = '';
     $accession = '';
@@ -131,6 +136,7 @@ class chado_base__dbxref_id extends TripalField {
     // If the field already has a value then it will come through the $items
     // array.  This happens when editing an existing record.
     if (array_key_exists($delta, $items)) {
+      $fk_val = $items[$delta][$field_table . '__' . $field_column];
       $dbxref_id = $items[$delta]['dbxref__dbxref_id'];
       $db_id = $items[$delta]['dbxref__db_id'];
       $accession = $items[$delta]['dbxref__accession'];
@@ -140,6 +146,7 @@ class chado_base__dbxref_id extends TripalField {
 
     // Check $form_state['values'] to see if an AJAX call set the values.
     if (array_key_exists('values', $form_state)) {
+      $fk_val = tripal_chado_get_field_form_values($field_name, $form_state, 0, $field_table . '__' . $field_column);
       $dbxref_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, 'dbxref__dbxref_id');
       $db_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, "dbxref__db_id");
       $accession = tripal_chado_get_field_form_values($field_name, $form_state, 0, "dbxref__accession");
@@ -177,11 +184,16 @@ class chado_base__dbxref_id extends TripalField {
       //'#collapsed' => $collapsed,
     );
 
-    $form['value'] = array(
+    $widget['value'] = array(
       '#type' => 'value',
       '#value' => $items[0]['value'],
     );
 
+    $widget[$field_table . '__' . $field_column] = array(
+      '#type' => 'value',
+      '#default_value' => $fk_val,
+    );
+
     $widget['dbxref__dbxref_id'] = array(
       '#type' => 'value',
       '#default_value' => $dbxref_id,
@@ -231,10 +243,10 @@ class chado_base__dbxref_id extends TripalField {
       '#size' => 20,
       '#disabled' => $db_id ? FALSE : TRUE,
     );
-    $widget['links'] = array(
-      '#type' => 'item',
-      '#markup' => l('Add a new database', 'admin/tripal/chado/tripal_db/add', array('attributes' => array('target' => '_blank')))
-    );
+//     $widget['links'] = array(
+//       '#type' => 'item',
+//       '#markup' => l('Add a new database', 'admin/tripal/chado/tripal_db/add', array('attributes' => array('target' => '_blank')))
+//     );
   }
 
   /**
@@ -249,43 +261,41 @@ class chado_base__dbxref_id extends TripalField {
     $field_table = $field['settings']['chado_table'];
     $field_column = $field['settings']['chado_column'];
 
+
     // Set some defauls for the empty record
     $entity->{$field_name}['und'][0] = array(
       'value' => array(),
+      $field_table . '__' . $field_column => '',
       'dbxref__dbxref_id' => '',
       'dbxref__db_id' => '',
       'dbxref__accession' => '',
       'dbxref__version' => '',
       'dbxref__description' => '',
     );
+
     // Get the primary dbxref record (if it's not NULL).  Because we have a
     // dbxref_id passed in by the base record, we will only have one record.
     if ($record->$field_column) {
-      $columns = array('*');
-      $match = array('dbxref_id' => $record->$field_column->$field_column);
-      $options = array('return_array' => TRUE);
-      $dbxrefs = chado_select_record('dbxref', $columns, $match, $options);
-      if (count($dbxrefs) > 0) {
-        $dbxref = $dbxrefs[0];
-        $value = $dbxref->db_id->name . ':' . $dbxref->accession;
-        $URL = '';
-        if ($dbxref->db_id->urlprefix) {
-          $URL = l($value, $dbxref->db_id->urlprefix . '/' . $dbxref->accession);
-        }
-
-        $entity->{$field_name}['und'][0] = array(
-          'value' => array(
-             'namespace' => $dbxref->db_id->name,
-             'accession' => $dbxref->accession,
-             'schema:URL' => $URL,
-           ),
-          'dbxref__dbxref_id' => $dbxref->dbxref_id,
-          'dbxref__db_id' => $dbxref->db_id,
-          'dbxref__accession' => $dbxref->accession,
-          'dbxref__version' => $dbxref->version,
-          'dbxref__description' => $dbxref->description,
-        );
+      $dbxref = $record->$field_column;
+      $value = $dbxref->db_id->name . ':' . $dbxref->accession;
+      $URL = '';
+      if ($dbxref->db_id->urlprefix) {
+        $URL = l($value, $dbxref->db_id->urlprefix . '/' . $dbxref->accession);
       }
+
+      $entity->{$field_name}['und'][0] = array(
+        'value' => array(
+          'namespace' => $dbxref->db_id->name,
+          'accession' => $dbxref->accession,
+          'URL' => $URL,
+        ),
+        $field_table . '__' . $field_column => $record->$field_column->$field_column,
+        'dbxref__dbxref_id' => $dbxref->dbxref_id,
+        'dbxref__db_id' => $dbxref->db_id->db_id,
+        'dbxref__accession' => $dbxref->accession,
+        'dbxref__version' => $dbxref->version,
+        'dbxref__description' => $dbxref->description,
+      );
     }
   }
 }
@@ -295,6 +305,12 @@ class chado_base__dbxref_id extends TripalField {
  */
 function chado_base__dbxref_id_widget_validate($element, &$form_state) {
   $field_name = $element['#parents'][0];
+  $field = $form_state['field'][$field_name]['und']['field'];
+  $settings = $field['settings'];
+  $field_name = $field['field_name'];
+  $field_type = $field['type'];
+  $field_table = $field['settings']['chado_table'];
+  $field_column = $field['settings']['chado_column'];
 
   // If the form ID is field_ui_field_edit_form, then the user is editing the
   // field's values in the manage fields form of Drupal.  We don't want
@@ -304,6 +320,7 @@ function chado_base__dbxref_id_widget_validate($element, &$form_state) {
   }
 
   // Get the field values.
+  $fk_value = tripal_chado_get_field_form_values($field_name, $form_state, 0, $field_table . '__' . $field_column);
   $dbxref_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, 'dbxref__dbxref_id');
   $db_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, "dbxref__db_id");
   $accession = tripal_chado_get_field_form_values($field_name, $form_state, 0, "dbxref__accession");
@@ -331,6 +348,7 @@ function chado_base__dbxref_id_widget_validate($element, &$form_state) {
   // field.
   if (!$db_id) {
     tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__', 0, 'dbxref__dbxref_id');
+    tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__', 0, $field_table . '__' . $field_column);
   }
   // If the dbxref_id does not match the db_id + accession then the user
   // has selected a new dbxref record and we need to update the hidden
@@ -338,6 +356,7 @@ function chado_base__dbxref_id_widget_validate($element, &$form_state) {
   if ($db_id and $accession) {
     $dbxref = chado_generate_var('dbxref', array('db_id' => $db_id, 'accession' => $accession));
     if ($dbxref and $dbxref->dbxref_id != $dbxref_id) {
+      tripal_chado_set_field_form_values($field_name, $form_state, $dbxref->dbxref_id, 0, $field_table . '__' . $field_column);
       tripal_chado_set_field_form_values($field_name, $form_state, $dbxref->dbxref_id, 0, 'dbxref__dbxref_id');
     }
   }
@@ -365,40 +384,4 @@ function chado_base__dbxref_id_widget_form_ajax_callback($form, $form_state) {
   return $form[$field_name];
 }
 
-function theme_chado_base__dbxref_id_widget($variables) {
-  $element = $variables['element'];
-
-  $layout = "
-      <div class=\"primary-dbxref-widget\">
-        <div class=\"primary-dbxref-widget-item\">" .
-        drupal_render($element['dbxref__db_id']) . "
-        </div>
-        <div class=\"primary-dbxref-widget-item\">" .
-        drupal_render($element['dbxref__accession']) . "
-        </div>
-        <div class=\"primary-dbxref-widget-item\">" .
-        drupal_render($element['dbxref__version']) . "
-        </div>
-        <div class=\"primary-dbxref-widget-item\">" .
-        drupal_render($element['dbxref__description']) . "
-        </div>
-        <div class=\"primary-dbxref-widget-links\">" . drupal_render($element['links']) . "</div>
-      </div>
-    ";
-
-  //   $classes = array();
-  //   $classes[] = 'collapsible';
-  //   $theme_settings = $element['#theme_settings'];
-  //   if ($theme_settings['#collapsed'] == FALSE) {
-  //     $classes[] = 'collapsed';
-  //   }
-  $fieldset = array(
-    '#title' => $element['#title'],
-    '#value' => '',
-    '#description' => $element['#description'],
-    '#children' => $layout,
-    //    '#attributes' => array('class' => $classes),
-  );
-
-  return theme('fieldset', array('element' => $fieldset));
-}
+

+ 0 - 188
tripal_chado/includes/fields/chado_base__md5checksum.inc

@@ -1,188 +0,0 @@
-<?php
-
-class chado_base__md5checksum  extends TripalField {
-
-  /**
-   * @see TripalField::field_info()
-   */
-  function field_info() {
-    return array(
-      'label' => t('MD5 checksum'),
-      'description' => t('A field for generating MD5 checksum for a sequence.'),
-      'default_widget' => 'chado_base__md5checksum_widget',
-      'default_formatter' => 'chado_base__md5checksum_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    );
-  }
-
-  /**
-   * @see TripalField::attach_info()
-   */
-  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'];
-
-    $md5_fieldname = '';
-    $schema = chado_get_schema($table_name);
-    // Only attach to tables that have md5checksum columns. Currently for
-    // Chado v1.3 this is only the  feature  and expression tables.
-    if (array_key_exists('md5checksum', $schema['fields'])) {
-      if ($table_name == 'feature') {
-        $md5_fieldname = 'residues';
-      }
-      else if ($table_name == 'expression') {
-        $md5_fieldname = 'uniquename';
-      }
-      else {
-        return $field_info;
-      }
-    }
-    else {
-      return $field_info;
-    }
-
-
-
-    // Create an array with information about this field.
-    $field_info = array(
-      'field_name' => 'base__md5checksum',
-      'field_type' => 'chado_base__md5checksum',
-      'widget_type' => 'chado_base__md5checksum_widget',
-      'description' => 'The MD5 checksum for the sequence.',
-      'label' => 'MD5 Checksum',
-      'is_required' => 0,
-      'storage' => 'field_chado_storage',
-      'widget_settings' => array(
-        'display_label' => 1,
-        'md5_fieldname' => $md5_fieldname,
-      ),
-      'field_settings' => array(
-        'chado_table' => $table_name,
-        'chado_column' => 'md5checksum',
-        'semantic_web' => array(
-          'name' => 'md5_checksum',
-          'accession' => 'md5_checksum',
-          'ns' => 'local',
-          'nsurl' => '',
-        ),
-      ),
-    );
-    return $field_info;
-  }
-
-  /**
-   * @see TripalField::widget_info()
-   */
-  function widget_info() {
-    return array(
-      'label' => t('MD5 Checksum Checkbox'),
-      'field types' => array('chado_base__md5checksum'),
-    );
-  }
-
-  /**
-   * @see TripalField::formatter_info()
-   */
-  function formatter_info() {
-    return array(
-      'label' => t('MD5 Checksum'),
-      'field types' => array('chado_base__md5checksum'),
-      'settings' => array(
-      ),
-    );
-  }
-
-  /**
-   * @see TripalField::formatter_view()
-   */
-  function formatter_view(&$element, $entity_type, $entity, $field,
-      $instance, $langcode, $items, $display) {
-    foreach ($items as $delta => $item) {
-      $content = key_exists('value', $item) ? $item['value'] : '';
-      $element[$delta] = array(
-        // We create a render array to produce the desired markup,
-        '#type' => 'markup',
-        '#markup' => $content,
-      );
-    }
-  }
-
-  /**
-   * @see TripalField::widget_form()
-   */
-  function widget_form(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-    $settings = $field['settings'];
-    $field_name = $field['field_name'];
-    $field_type = $field['type'];
-    $field_table = $field['settings']['chado_table'];
-    $field_column = $field['settings']['chado_column'];
-
-    $form['value'] = array(
-      '#type' => 'value',
-      '#value' => $items[0]['value'],
-    );
-
-    $widget[$field_table . '__md5checksum'] = array(
-      '#type' => 'checkbox',
-      '#title' => $element['#title'],
-      '#description' => $element['#description'],
-      '#options' => array(0, 1),
-      '#default_value' => '',
-      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
-      '#delta' => $delta,
-      '#element_validate' => array('chado_base__md5checksum_widget_validate'),
-    );
-  }
-
-
-  /**
-   * @see TripalField::load()
-   */
-  function load($field, $entity, $details) {
-    $record = $details['record'];
-    $settings = $field['settings'];
-
-    $field_name = $field['field_name'];
-    $field_type = $field['type'];
-    $field_table = $field['settings']['chado_table'];
-    $field_column = $field['settings']['chado_column'];
-
-    $entity->{$field_name}['und'][0]['value'] = $record->md5checksum;
-    $entity->{$field_name}['und'][0][$field_table . '__md5checksum'] = $record->md5checksum;
-  }
-}
-
-/**
- * Callback function for validating the chado_base__md5checksum_widget.
- */
-function chado_base__md5checksum_widget_validate($element, &$form_state) {
-  $field_name = $element['#parents'][0];
-  $field = $form_state['field'][$field_name]['und']['field'];
-  $settings = $field['settings'];
-  $field_name = $field['field_name'];
-  $field_type = $field['type'];
-  $field_table = $field['settings']['chado_table'];
-  $field_column = $field['settings']['chado_column'];
-
-  // Calculate the md5 checksum for the sequence only if md5 box is checked and
-  // the residues exist.
-  $residues = tripal_chado_get_field_form_values('feature__residues', $form_state, 0, 'feature__residues');
-  if ($residues) {
-    $residues = preg_replace('/\s/', '', $residues);
-    tripal_chado_set_field_form_values($field_name, $form_state, md5($residues), 0, $field_table . '__md5checksum');
-  }
-  else {
-    // Otherwise, remove the md5 value
-    tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__', 0, $field_table . '__md5checksum');
-  }
-}

+ 37 - 12
tripal_chado/includes/fields/chado_feature__residues.inc

@@ -83,7 +83,7 @@ class chado_feature__residues extends TripalField {
    */
   function widget_info() {
     return array(
-      'label' => t('Sequences'),
+      'label' => t('Sequence'),
       'field types' => array('chado_feature__residues'),
     );
   }
@@ -118,6 +118,10 @@ class chado_feature__residues extends TripalField {
     $feature = $entity->chado_record;
 
     foreach ($items as $delta => $item) {
+      // If there are no residues then skip this one.
+      if (!array_key_exists('residues', $item['value'])) {
+        continue;
+      }
 
       $residues = $item['value']['residues'];
       $label = $item['value']['label'];
@@ -147,7 +151,14 @@ class chado_feature__residues extends TripalField {
     $field_table = $field['settings']['chado_table'];
     $field_column = $field['settings']['chado_column'];
 
-    $form['value'] = array(
+    // This field provides several items if an alignment for the feature
+    // is present.  We don't want widgets for those.  Just for the first
+    // one which should always be the residues for the feature table.
+    if ($delta > 0) {
+      return;
+    }
+
+    $widget['value'] = array(
       '#type' => 'value',
       '#value' => $items[$delta]['value'],
     );
@@ -156,7 +167,7 @@ class chado_feature__residues extends TripalField {
       '#title' => $element['#title'],
       '#description' => $element['#description'],
       '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
-      '#default_value' => count($items) > 0 ? $items[0]['value'] : '',
+      '#default_value' => $items[$delta]['feature__residues'],
       '#delta' => $delta,
       '#element_validate' => array('chado_feature__residues_widget_validate'),
       '#cols' => 30,
@@ -171,15 +182,24 @@ class chado_feature__residues extends TripalField {
     $feature = $details['record'];
     $num_seqs = 0;
 
-    // we don't want to get the sequence for traditionally large types. They are
+
+    // We don't want to get the sequence for traditionally large types. They are
     // too big,  bog down the web browser, take longer to load and it's not
     // reasonable to print them on a page.
-
-    if(strcmp($feature->type_id->name,'scaffold') !=0 and
-       strcmp($feature->type_id->name,'chromosome') !=0 and
-       strcmp($feature->type_id->name,'supercontig') !=0 and
-       strcmp($feature->type_id->name,'pseudomolecule') !=0) {
-
+    if(strcmp($feature->type_id->name,'scaffold') == 0 or
+       strcmp($feature->type_id->name,'chromosome') == 0 or
+       strcmp($feature->type_id->name,'supercontig') == 0 or
+       strcmp($feature->type_id->name,'pseudomolecule') == 0) {
+      $entity->{$field_name}['und'][$num_seqs]['value'] = array(
+        '@type' => 'SO:0000110',
+        'type' => 'sequence_feature',
+        'label' => 'Residues',
+        'defline' => ">This sequence is too large for this display.",
+        'residues' => '',
+      );
+      $entity->{$field_name}['und'][$num_seqs]['feature__residues'] = '';
+    }
+    else {
       $feature = chado_expand_var($feature,'field','feature.residues');
       if ($feature->residues) {
         $entity->{$field_name}['und'][$num_seqs]['value'] = array(
@@ -189,9 +209,14 @@ class chado_feature__residues extends TripalField {
           'defline' => tripal_get_fasta_defline($feature, '', NULL, '', strlen($feature->residues)),
           'residues' => $feature->residues,
         );
-        $entity->{$field_name}['und'][$num_seqs++]['residues'] = $feature->residues;
+        $entity->{$field_name}['und'][$num_seqs]['feature__residues'] = $feature->residues;
+      }
+      else {
+        $entity->{$field_name}['und'][$num_seqs]['value'] = array();
+        $entity->{$field_name}['und'][$num_seqs]['feature__residues'] = '';
       }
     }
+    $num_seqs++;
 
     // Add in the protein sequences
     $values = array(
@@ -631,7 +656,7 @@ function chado_feature__residues_widget_validate($element, &$form_state) {
   $field_name = $element['#parents'][0];
 
   // Remove any white spaces.
-  $residues = tripal_chado_get_field_form_values($field_name, $form_state);
+  $residues = tripal_chado_get_field_form_values($field_name, $form_state, 0, 'feature__residues');
   if ($residues) {
     $residues = preg_replace('/\s/', '', $residues);
     tripal_chado_set_field_form_values($field_name, $form_state, $residues, 0, 'feature__residues');

+ 110 - 148
tripal_chado/includes/fields/chado_feature__seqlen.inc

@@ -1,164 +1,127 @@
 <?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_feature__seqlen_info() {
-  return array(
-    'label' => t('Sequence length'),
-    'description' => t('A field for calculating the length of a sequence.'),
-    'default_widget' => 'chado_feature__seqlen_widget',
-    'default_formatter' => 'chado_feature__seqlen_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_feature__seqlen_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'];
+class chado_feature__seqlen extends TripalField {
+  /**
+   * @see TripalField::field_info()
+   */
+  function field_info() {
+    return array(
+      'label' => t('Sequence length'),
+      'description' => t('A field for calculating the length of a sequence.'),
+      'default_widget' => 'chado_feature__seqlen_widget',
+      'default_formatter' => 'chado_feature__seqlen_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    );
+  }
+  /**
+   * @see TripalField::attach_info()
+   */
+  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  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' => array(
+            'name' => 'Sequence length',
+            'accession' => '1249',
+            'ns' => 'data',
+            'nsurl' => 'http://edamontology.org/',
+          ),
+        ),
+      );
+    }
 
-  // If  this is not the feature table then we don't want to attach.
-  if ($table_name != 'feature') {
     return $field_info;
   }
-
-  $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' => array(
-        'name' => '',
-        'accession' => '',
-        'ns' => '',
-        'nsurl' => '',
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('Sequence Length'),
+      'field types' => array('chado_feature__seqlen'),
+    );
+  }
+  /**
+   * @see TripalField::formatter_info()
+   */
+  function formatter_info() {
+    return array(
+      'label' => t('Residues Length'),
+      'field types' => array('chado_feature__seqlen'),
+      'settings' => array(
       ),
-    ),
-  );
-
-  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_feature__seqlen_widget_info() {
-  return array(
-    'label' => t('Sequence Length'),
-    'field types' => array('chado_feature__seqlen'),
-  );
-}
-/**
- * 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_feature__seqlen_formatter_info() {
-  return array(
-    'label' => t('Residues Length'),
-    'field types' => array('chado_feature__seqlen'),
-    '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_feature__seqlen_formatter(&$element, $entity_type, $entity, $field,
-    $instance, $langcode, $items, $display) {
+  /**
+   * @see TripalField::formatter_view()
+   */
+  function formatter_view(&$element, $entity_type, $entity, $field,
+      $instance, $langcode, $items, $display) {
 
-  foreach ($items as $delta => $item) {
-    $content = key_exists('value', $item) ? $item['value'] : '';
-    $element[$delta] = array(
-      // We create a render array to produce the desired markup,
-      '#type' => 'markup',
-      '#markup' => $content,
-    );
+    foreach ($items as $delta => $item) {
+      $element[$delta] = array(
+        '#type' => 'markup',
+        '#markup' => $item['value'],
+      );
+    }
   }
-}
 
-/**
- *
- * @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_feature__seqlen_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
+  /**
+   * @see TripalField::widget_form()
+   */
+  function widget_form(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
 
-  $settings = $field['settings'];
-  $field_name = $field['field_name'];
-  $field_type = $field['type'];
-  $field_table = $field['settings']['chado_table'];
-  $field_column = $field['settings']['chado_column'];
+    $settings = $field['settings'];
+    $field_name = $field['field_name'];
+    $field_type = $field['type'];
+    $field_table = $field['settings']['chado_table'];
+    $field_column = $field['settings']['chado_column'];
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['value'],
+    );
 
-  $form['value'] = array(
-    '#type' => 'value',
-    '#value' => $items[$delta]['value'],
-  );
+    $widget['feature__seqlen'] =  array(
+      '#type' => 'value',
+      '#value' => 0,
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#delta' => $delta,
+      '#element_validate' => array('chado_feature__seqlen_widget_validate'),
+    );
+  }
 
-  $widget['feature__seqlen'] =  array(
-    '#type' => 'hidden',
-    '#title' => $element['#title'],
-    '#description' => $element['#description'],
-    '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
-    '#delta' => $delta,
-    '#element_validate' => array('chado_feature__seqlen_widget_validate'),
-  );
 }
+
 /**
  * Callback function for validating the chado_feature__seqlen_widget.
  */
@@ -166,8 +129,7 @@ function chado_feature__seqlen_widget_validate($element, &$form_state) {
   $field_name = $element['#parents'][0];
 
   // Get the residues so we can calculate teh length.
-  $residues = tripal_chado_get_field_form_values('feature__residues', $form_state);
-
+  $residues = tripal_chado_get_field_form_values('feature__residues', $form_state, 0, 'feature__residues');
   // Remove any white spaces.
   if ($residues) {
     $residues = preg_replace('/\s/', '', $residues);

+ 2 - 5
tripal_chado/includes/fields/chado_gene__transcripts.inc

@@ -43,7 +43,7 @@ class chado_gene__transcripts extends TripalField {
 
     // Initialize the field array.
     $field_info = array(
-      'field_name' => 'gene__transcripts',
+      'field_name' => 'gene_transcripts',
       'field_type' => 'chado_gene__transcripts',
       'widget_type' => 'chado_gene__transcripts_widget',
       'widget_settings' => array('display_label' => 1),
@@ -218,9 +218,6 @@ class chado_gene__transcripts extends TripalField {
    * @see TripalField::widget_form()
    */
   public function widget_form(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-    $form['value'] = array(
-      '#type' => 'value',
-      '#value' => $items[$delta]['value'],
-    );
+
   }
 }

+ 2 - 5
tripal_chado/includes/fields/chado_linker__contact.inc

@@ -64,7 +64,7 @@ class chado_linker__contact extends TripalField {
 
     // Initialize the field array.
     $field_info = array(
-      'field_name' => $table_name . '__contact',
+      'field_name' => $table_name . '_contact',
       'field_type' => 'chado_linker__contact',
       'widget_type' => 'chado_linker__contact_widget',
       'widget_settings' => array('display_label' => 1),
@@ -147,10 +147,7 @@ class chado_linker__contact extends TripalField {
   public function widget_form(&$widget, $form, $form_state, $field, $instance,
       $langcode, $items, $delta, $element) {
 
-    $form['value'] = array(
-      '#type' => 'value',
-      '#value' => $items[$delta]['value'],
-    );
+
   }
 
   /**

+ 321 - 365
tripal_chado/includes/fields/chado_linker__cvterm.inc

@@ -1,280 +1,338 @@
 <?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__cvterm_info() {
-  return array(
-    'label' => t('Annotations'),
-    'description' => t('This record can be annotated with terms
-          from other vocabularies.'),
-    'default_widget' => 'chado_linker__cvterm_widget',
-    'default_formatter' => 'chado_linker__cvterm_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__cvterm_attach_info($entity_type, $bundle, $target) {
-  $field_info = array();
 
-  // This field is only attached by the chado_linker__cvterm_addr field.
+class chado_linker__cvterm extends TripalField {
+  /**
+   * @see TripalField::field_info()
+   */
+  function field_info() {
+    return array(
+      'label' => t('Annotations'),
+      'description' => t('This record can be annotated with terms
+            from other vocabularies.'),
+      'default_widget' => 'chado_linker__cvterm_widget',
+      'default_formatter' => 'chado_linker__cvterm_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    );
+  }
+  /**
+   * @see TripalField::attach_info()
+   */
+  function attach_info($entity_type, $bundle, $target) {
+    $field_info = array();
 
-  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__cvterm_widget_info() {
-  return array(
-    'label' => t('Annotations'),
-    'field types' => array('chado_linker__cvterm'),
-    'description' => t('This record can be annotated with terms
-          from other vocabularies.'),
-  );
-}
-/**
- * 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__cvterm_formatter_info() {
-  return array(
-    'label' => t('Annotations'),
-    'field types' => array('chado_linker__cvterm'),
-    '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__cvterm_formatter(&$element, $entity_type, $entity, $field,
-    $instance, $langcode, $items, $display) {
-
-  $headers = array('Term', 'Definition', 'Is Not', 'Reference');
-  $rows = array();
-
-  $chado_table = $field['settings']['chado_table'];
-  foreach ($items as $delta => $item) {
-    if ($item[$chado_table . '__cvterm_id']) {
-      $cvterm = chado_generate_var('cvterm', array('cvterm_id' => $item[$chado_table . '__cvterm_id']));
-      $dbxref = $cvterm->dbxref_id;
-
-      // Build the accession.
-      $accession = $dbxref->db_id->name . ':' . $dbxref->accession;
-      if ($dbxref->db_id->urlprefix) {
-        $accession = l($accession, $dbxref->db_id->urlprefix . '/' . $dbxref->accession, array('attributes' => array('target' => '_blank')));
-      }
+    // This field is only attached by the chado_linker__cvterm_addr field.
 
-      // Build the publication reference.
-      $pub_ref = '';
-      $pub_id = $item[$chado_table . '__pub_id'];
-      if ($pub_id) {
-        $pub = chado_generate_var('pub', array('pub_id' => $pub_id));
-        $pub_ref = $pub->title;
-      }
-      $rows[] = array(
-        $accession,
-        $cvterm->definition,
-        $item[$chado_table . '__is_not'] ? 'Yes' : '',
-        '',
-      );
-    }
+    return $field_info;
   }
-
-  // the $table array contains the headers and rows array as well as other
-  // options for controlling the display of the table.  Additional
-  // documentation can be found here:
-  // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
-  $table = array(
-    'header' => $headers,
-    'rows' => $rows,
-    'attributes' => array(
-      'id' => "$chado_table-table-terms",
-      'class' => 'tripal-data-table'
-    ),
-    'caption' => '',
-    'sticky' => FALSE,
-    'colgroups' => array(),
-    'empty' => 'There are no annotations of this type',
-  );
-
-  $element[0] = array(
-    '#type' => 'markup',
-    '#markup' => theme_table($table),
-  );
-}
-/**
- *
- * @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__cvterm_widget(&$widget, $form, $form_state, $field,
-    $instance, $langcode, $items, $delta, $element) {
-
-  $entity = $form['#entity'];
-  $field_name = $field['field_name'];
-
-  $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;
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('Annotations'),
+      'field types' => array('chado_linker__cvterm'),
+      'description' => t('This record can be annotated with terms
+            from other vocabularies.'),
+    );
   }
-  $table_name = $matches[1];
-  $cv_id = $matches[2];
-
-  // Get the FK column that links to the base table.
-  $chado_table = $field['settings']['chado_table'];
-  $base_table = $field['settings']['base_table'];
-  $schema = chado_get_schema($chado_table);
-  $pkey = $schema['primary key'][0];
-  $fkeys = array_values($schema['foreign keys'][$base_table]['columns']);
-  $fkey = $fkeys[0];
-
-  // Get the field defaults.
-  $record_id = '';
-  $fkey_value = $element['#entity']->chado_record_id;
-  $cvterm_name = '';
-  $cvterm_id = '';
-  $is_not = '';
-  $cvterm = NULL;
-
-  // If the field already has a value then it will come through the $items
-  // array.  This happens when editing an existing record.
-  if (array_key_exists($delta, $items)) {
-    $record_id = $items[$delta]['value'];
-    $fkey_value = $items[$delta][$table_name . '__' . $fkey];
-    $cvterm_name = $items[$delta][$table_name . '--cvterm__name'];
-    $is_not = $items[$delta][$table_name . '__is_not'];
-    $cvterm_id = $items[$delta][$table_name . '__cvterm_id'];
+  /**
+   * @see TripalField::formatter_info()
+   */
+  function formatter_info() {
+    return array(
+      'label' => t('Annotations'),
+      'field types' => array('chado_linker__cvterm'),
+      'settings' => array(
+      ),
+    );
   }
+  /**
+   * @see TripalField::formatter_view()
+   */
+  function formatter_view(&$element, $entity_type, $entity, $field,
+      $instance, $langcode, $items, $display) {
+
+    $headers = array('Term', 'Definition', 'Is Not', 'Reference');
+    $rows = array();
+
+    $chado_table = $field['settings']['chado_table'];
+    foreach ($items as $delta => $item) {
+      if ($item[$chado_table . '__cvterm_id']) {
+        $cvterm = chado_generate_var('cvterm', array('cvterm_id' => $item[$chado_table . '__cvterm_id']));
+        $dbxref = $cvterm->dbxref_id;
+
+        // Build the accession.
+        $accession = $dbxref->db_id->name . ':' . $dbxref->accession;
+        if ($dbxref->db_id->urlprefix) {
+          $accession = l($accession, $dbxref->db_id->urlprefix . '/' . $dbxref->accession, array('attributes' => array('target' => '_blank')));
+        }
+
+        // Build the publication reference.
+        $pub_ref = '';
+        $pub_id = $item[$chado_table . '__pub_id'];
+        if ($pub_id) {
+          $pub = chado_generate_var('pub', array('pub_id' => $pub_id));
+          $pub_ref = $pub->title;
+        }
+        $rows[] = array(
+          $accession,
+          $cvterm->definition,
+          $item[$chado_table . '__is_not'] ? 'Yes' : '',
+          '',
+        );
+      }
+    }
+
+    // the $table array contains the headers and rows array as well as other
+    // options for controlling the display of the table.  Additional
+    // documentation can be found here:
+    // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
+    $table = array(
+      'header' => $headers,
+      'rows' => $rows,
+      'attributes' => array(
+        'id' => "$chado_table-table-terms",
+        'class' => 'tripal-data-table'
+      ),
+      'caption' => '',
+      'sticky' => FALSE,
+      'colgroups' => array(),
+      'empty' => 'There are no annotations of this type',
+    );
 
-  // Check $form_state['values'] to see if an AJAX call set the values.
-  if (array_key_exists('values', $form_state) and array_key_exists($delta, $form_state['values'])) {
-    $record_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name);
-    $fkey_value = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__' . $fkey);
-    $is_not = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__is_not');
-    $cvterm_name = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '--cvterm__name');
+    $element[0] = array(
+      '#type' => 'markup',
+      '#markup' => theme_table($table),
+    );
   }
+  /**
+   * @see TripalField::widget_form()
+   */
+  function widget_form(&$widget, $form, $form_state, $field, $instance,
+      $langcode, $items, $delta, $element) {
+
+    $entity = $form['#entity'];
+    $field_name = $field['field_name'];
+
+    $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];
+    $cv_id = $matches[2];
+
+    // Get the FK column that links to the base table.
+    $chado_table = $field['settings']['chado_table'];
+    $base_table = $field['settings']['base_table'];
+    $schema = chado_get_schema($chado_table);
+    $pkey = $schema['primary key'][0];
+    $fkeys = array_values($schema['foreign keys'][$base_table]['columns']);
+    $fkey = $fkeys[0];
+
+    // Get the field defaults.
+    $record_id = '';
+    $fkey_value = $element['#entity']->chado_record_id;
+    $cvterm_name = '';
+    $cvterm_id = '';
+    $is_not = '';
+    $cvterm = NULL;
+
+    // If the field already has a value then it will come through the $items
+    // array.  This happens when editing an existing record.
+    if (array_key_exists($delta, $items)) {
+      $record_id = $items[$delta]['value'];
+      $fkey_value = $items[$delta][$table_name . '__' . $fkey];
+      $cvterm_name = $items[$delta][$table_name . '--cvterm__name'];
+      $is_not = $items[$delta][$table_name . '__is_not'];
+      $cvterm_id = $items[$delta][$table_name . '__cvterm_id'];
+    }
+
+    // Check $form_state['values'] to see if an AJAX call set the values.
+    if (array_key_exists('values', $form_state) and array_key_exists($delta, $form_state['values'])) {
+      $record_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name);
+      $fkey_value = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__' . $fkey);
+      $is_not = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__is_not');
+      $cvterm_name = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '--cvterm__name');
+    }
+
+    if ($cvterm_name) {
+      $cvterm = chado_generate_var('cvterm', array('cv_id' => $cv_id, 'name' => $cvterm_name));
+    }
+
+    $schema = chado_get_schema('cvterm');
+    $options = tripal_get_cv_select_options();
+
+    $widget['#table_name'] = $chado_table;
+    $widget['#fkey_field'] = $fkey;
+    $widget['#element_validate'] = array('chado_linker__cvterm_widget_validate');
+    $widget['#theme'] = 'chado_linker__cvterm_widget';
+    $widget['#prefix'] =  "<span id='$table_name-$delta'>";
+    $widget['#suffix'] =  "</span>";
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['value'],
+    );
+
+    $widget[$table_name . '__' . $pkey] = array(
+      '#type' => 'value',
+      '#default_value' => $record_id,
+    );
+    $widget[$table_name . '--cvterm__cv_id--cv__cv_id'] = array(
+      '#type' => 'value',
+      '#default_value' => $cv_id,
+    );
+    $widget[$table_name . '__cvterm_id'] = array(
+      '#type' => 'value',
+      '#default_value' => $cvterm ? $cvterm->cvterm_id : '',
+    );
+    $widget[$table_name . '__' . $fkey] = array(
+      '#type' => 'value',
+      '#default_value' => $fkey_value,
+    );
+
+    $widget[$table_name . '--cvterm__name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Term Name'),
+      '#default_value' => $cvterm_name,
+      '#required' => $element['#required'],
+      '#maxlength' => array_key_exists('length', $schema['fields']['name']) ? $schema['fields']['name']['length'] : 255,
+      '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/cvterm/' . $cv_id,
+      '#ajax' => array(
+        'callback' => "chado_linker__cvterm_widget_form_ajax_callback",
+        'wrapper' => "$table_name-$delta",
+        'effect' => 'fade',
+        'method' => 'replace'
+      ),
+    );
+
+    $widget[$table_name . '__is_not'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Is Not'),
+      '#default_value' => $is_not,
+      '#required' => $element['#required'],
+    );
+
+    $widget[$table_name . '--cvterm__definition'] = array(
+      '#type' => 'item',
+      '#markup' => '',
+    );
 
-  if ($cvterm_name) {
-    $cvterm = chado_generate_var('cvterm', array('cv_id' => $cv_id, 'name' => $cvterm_name));
   }
 
-  $schema = chado_get_schema('cvterm');
-  $options = tripal_get_cv_select_options();
-
-  $widget['#table_name'] = $chado_table;
-  $widget['#fkey_field'] = $fkey;
-  $widget['#element_validate'] = array('chado_linker__cvterm_widget_validate');
-  $widget['#theme'] = 'chado_linker__cvterm_widget';
-  $widget['#prefix'] =  "<span id='$table_name-$delta'>";
-  $widget['#suffix'] =  "</span>";
-
-  $form['value'] = array(
-    '#type' => 'value',
-    '#value' => $items[$delta]['value'],
-  );
-
-  $widget[$table_name . '__' . $pkey] = array(
-    '#type' => 'value',
-    '#default_value' => $record_id,
-  );
-  $widget[$table_name . '--cvterm__cv_id--cv__cv_id'] = array(
-    '#type' => 'value',
-    '#default_value' => $cv_id,
-  );
-  $widget[$table_name . '__cvterm_id'] = array(
-    '#type' => 'value',
-    '#default_value' => $cvterm ? $cvterm->cvterm_id : '',
-  );
-  $widget[$table_name . '__' . $fkey] = array(
-    '#type' => 'value',
-    '#default_value' => $fkey_value,
-  );
-
-  $widget[$table_name . '--cvterm__name'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Term Name'),
-    '#default_value' => $cvterm_name,
-    '#required' => $element['#required'],
-    '#maxlength' => array_key_exists('length', $schema['fields']['name']) ? $schema['fields']['name']['length'] : 255,
-    '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/cvterm/' . $cv_id,
-    '#ajax' => array(
-      'callback' => "chado_linker__cvterm_widget_form_ajax_callback",
-      'wrapper' => "$table_name-$delta",
-      'effect' => 'fade',
-      'method' => 'replace'
-    ),
-  );
-
-  $widget[$table_name . '__is_not'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Is Not'),
-    '#default_value' => $is_not,
-    '#required' => $element['#required'],
-  );
-
-  $widget[$table_name . '--cvterm__definition'] = array(
-    '#type' => 'item',
-    '#markup' => '',
-  );
+  /**
+   * @see TripalField::load()
+   */
+  function load($field, $entity, $details) {
+
+    $record = $details['record'];
+
+    $field_name = $field['field_name'];
+    $field_type = $field['type'];
+    $field_table = $field['settings']['chado_table'];
+    $field_column = $field['settings']['chado_column'];
+
+    $matches = array();
+    preg_match('/(.*?)__(\d+)/', $field_name, $matches);
+    $table_name = $matches[1];
+    $cv_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 . '__' . $fkey_lcolumn => '',
+      $field_table . '__' . 'cvterm_id' => '',
+      // The pub column is present in the cell_line_cvterm, feature_cvterm,
+      // library_cvterm, phenotype_comparision_cvterm, phenotype_cvterm,
+      // stock_cvterm, and stock_relationship_cvterm.
+      $field_table . '__' . 'pub_id' => '',
+      // The is_not column is present in feature_cvterm and stock_cvterm tables.
+      $field_table . '__' . 'is_not' => '',
+      // The rank column is present in the cell_line_cvterm, expression_cvterm,
+      // feature_cvterm, phenotype_comparision_cvterm, phenotype_cvterm,
+      // and stock_cvterm tables.
+      $field_table . '__' . 'rank' => '',
+      // The cvterm_type_id is present in the expression_cvterm table.
+      $field_table . '--' . 'cvterm_type_id' => '',
+      // The following field are to help link the cvterm.
+      $field_table . '--' . 'cvterm__cv_id--cv__cv_id' => '',
+      $field_table . '--' . 'cvterm__name' => '',
+    );
 
+    // Get the annotations associated with this base record for this fields type.
+    $columns = array('*');
+    $match = array(
+      $fkey_lcolumn => $record->$fkey_rcolumn,
+      'cvterm_id' => array(
+        'cv_id' => $cv_id,
+      ),
+    );
+    $options = array(
+      'return_array' => TRUE,
+      'order_by' => array('rank' => 'ASC')
+    );
+    $fcvterms = chado_select_record($field_table, $columns, $match, $options);
+    for ($i = 0; $i < count($fcvterms); $i++) {
+      $linker = $fcvterms[$i];
+      $cvterm = chado_generate_var('cvterm', array('cvterm_id' => $linker->cvterm_id));
+      $entity->{$field_name}['und'][$i] = array(
+        'value' => $linker->$pkey,
+        $field_table . '__' . $fkey_lcolumn => $linker->$fkey_lcolumn,
+        $field_table . '__' . 'cvterm_id' => $linker->cvterm_id,
+        $field_table . '__' . 'pub_id' => property_exists($linker, 'pub_id') ? $linker->pub_id : '',
+        $field_table . '__' . 'is_not' => property_exists($linker, 'is_not') ? $linker->is_not : '',
+        $field_table . '__' . 'rank' => property_exists($linker, 'rank') ? $linker->rank : '',
+        $field_table . '__' . 'cvterm_type_id' => property_exists($linker, 'cvterm_type_id') ? $linker->cvterm_type_id : '',
+        $field_table . '--' . 'cvterm__cv_id--cv__cv_id' => $cvterm->cv_id->cv_id,
+        $field_table . '--' . 'cvterm__name' => $cvterm->name,
+      );
+    }
+  }
 }
+
 /**
- * An Ajax callback for the dbxref widget.
+ * Theme function for the dbxref_id_widget.
+ *
+ * @param $variables
  */
-function chado_linker__cvterm_widget_form_ajax_callback($form, $form_state) {
+function theme_chado_linker__cvterm_widget($variables) {
+  $element = $variables['element'];
 
-  $field_name = $form_state['triggering_element']['#parents'][0];
-  $delta = $form_state['triggering_element']['#parents'][2];
+  // These two fields were added to the widget to help identify the fields
+  // for layout.
+  $table_name = $element['#table_name'];
+  $fkey = $element['#fkey_field'];
 
+  $layout = "
+      <div class=\"annotation-cvterm-widget\">
+        <div class=\"annotation-cvterm-widget-item\">" .
+        drupal_render($element[$table_name . '--cvterm__cv_id--cv__cv_id']) . "
+        </div>
+        <div class=\"annotation-cvterm-widget-item\">" .
+        drupal_render($element[$table_name . '--cvterm__name']) . "
+        </div>
+        <div class=\"annotation-cvterm-widget-item\">" .
+        drupal_render($element[$table_name . '__is_not']) . "
+        </div>
+      </div>
+    ";
 
-  return $form[$field_name]['und'][$delta];
+  return $layout;
 }
-
 /**
  * Callback function for validating the chado_linker__cvterm_widget.
  */
@@ -325,115 +383,13 @@ function chado_linker__cvterm_widget_validate($element, &$form_state) {
 
 }
 /**
- * Theme function for the dbxref_id_widget.
- *
- * @param $variables
+ * An Ajax callback for the dbxref widget.
  */
-function theme_chado_linker__cvterm_widget($variables) {
-  $element = $variables['element'];
-
-  // These two fields were added to the widget to help identify the fields
-  // for layout.
-  $table_name = $element['#table_name'];
-  $fkey = $element['#fkey_field'];
-
-  $layout = "
-    <div class=\"annotation-cvterm-widget\">
-      <div class=\"annotation-cvterm-widget-item\">" .
-        drupal_render($element[$table_name . '--cvterm__cv_id--cv__cv_id']) . "
-      </div>
-      <div class=\"annotation-cvterm-widget-item\">" .
-        drupal_render($element[$table_name . '--cvterm__name']) . "
-      </div>
-      <div class=\"annotation-cvterm-widget-item\">" .
-        drupal_render($element[$table_name . '__is_not']) . "
-      </div>
-    </div>
-  ";
+function chado_linker__cvterm_widget_form_ajax_callback($form, $form_state) {
 
-  return $layout;
-}
+  $field_name = $form_state['triggering_element']['#parents'][0];
+  $delta = $form_state['triggering_element']['#parents'][2];
 
-/**
- * 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__cvterm_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'];
-
-  $matches = array();
-  preg_match('/(.*?)__(\d+)/', $field_name, $matches);
-  $table_name = $matches[1];
-  $cv_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 . '__' . $fkey_lcolumn => '',
-    $field_table . '__' . 'cvterm_id' => '',
-    // The pub column is present in the cell_line_cvterm, feature_cvterm,
-    // library_cvterm, phenotype_comparision_cvterm, phenotype_cvterm,
-    // stock_cvterm, and stock_relationship_cvterm.
-    $field_table . '__' . 'pub_id' => '',
-    // The is_not column is present in feature_cvterm and stock_cvterm tables.
-    $field_table . '__' . 'is_not' => '',
-    // The rank column is present in the cell_line_cvterm, expression_cvterm,
-    // feature_cvterm, phenotype_comparision_cvterm, phenotype_cvterm,
-    // and stock_cvterm tables.
-    $field_table . '__' . 'rank' => '',
-    // The cvterm_type_id is present in the expression_cvterm table.
-    $field_table . '--' . 'cvterm_type_id' => '',
-    // The following field are to help link the cvterm.
-    $field_table . '--' . 'cvterm__cv_id--cv__cv_id' => '',
-    $field_table . '--' . 'cvterm__name' => '',
-  );
-
-  // Get the annotations associated with this base record for this fields type.
-  $columns = array('*');
-  $match = array(
-    $fkey_lcolumn => $record->$fkey_rcolumn,
-    'cvterm_id' => array(
-      'cv_id' => $cv_id,
-    ),
-  );
-  $options = array(
-    'return_array' => TRUE,
-    'order_by' => array('rank' => 'ASC')
-  );
-  $fcvterms = chado_select_record($field_table, $columns, $match, $options);
-  for ($i = 0; $i < count($fcvterms); $i++) {
-    $linker = $fcvterms[$i];
-    $cvterm = chado_generate_var('cvterm', array('cvterm_id' => $linker->cvterm_id));
-    $entity->{$field_name}['und'][$i] = array(
-      'value' => $linker->$pkey,
-      $field_table . '__' . $fkey_lcolumn => $linker->$fkey_lcolumn,
-      $field_table . '__' . 'cvterm_id' => $linker->cvterm_id,
-      $field_table . '__' . 'pub_id' => property_exists($linker, 'pub_id') ? $linker->pub_id : '',
-      $field_table . '__' . 'is_not' => property_exists($linker, 'is_not') ? $linker->is_not : '',
-      $field_table . '__' . 'rank' => property_exists($linker, 'rank') ? $linker->rank : '',
-      $field_table . '__' . 'cvterm_type_id' => property_exists($linker, 'cvterm_type_id') ? $linker->cvterm_type_id : '',
-      $field_table . '--' . 'cvterm__cv_id--cv__cv_id' => $cvterm->cv_id->cv_id,
-      $field_table . '--' . 'cvterm__name' => $cvterm->name,
-    );
-  }
-}
 
+  return $form[$field_name]['und'][$delta];
+}

+ 163 - 180
tripal_chado/includes/fields/chado_linker__cvterm_adder.inc

@@ -1,194 +1,177 @@
 <?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.
- *
- * The field provides a widget for adding new vocabularies for cvterm
- * linker tables. This will allow cvterms to be grouped by vocabulary
- * ('category').
- *
- */
-function chado_linker__cvterm_adder_info() {
-  return array(
-    'label' => t('Add an Annotation Type'),
-    'description' => t('This record may have any number of types of
-      annotations. Use this field to first add the type.'),
-    'default_widget' => 'chado_linker__cvterm_adder_widget',
-    'default_formatter' => 'hidden',
-    'settings' => array(),
-    'storage' => array(
-      'type' => 'field_chado_storage',
-      'module' => 'tripal_chado',
-      'active' => TRUE
-    ),
-    'no_ui' => 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__cvterm_adder_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'];
-
+class chado_linker__cvterm_addr extends TripalField {
+  /**
+   * @see TripalField::field_info()
+   */
+  function field_info() {
+    return array(
+      'label' => t('Add an Annotation Type'),
+      'description' => t('This record may have any number of types of
+        annotations. Use this field to first add the type.'),
+      'default_widget' => 'chado_linker__cvterm_adder_widget',
+      'default_formatter' => 'hidden',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+      'no_ui' => TRUE
+    );
+  }
+  /**
+   * @see TripalField::attach_info()
+   */
+  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.
+    $cvterm_table = $table_name . '_cvterm';
+    if (!chado_table_exists($cvterm_table)) {
+      return $field_info;
+    }
+
+    // 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,
+      ),
+      '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.
+    );
 
-  // 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;
   }
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('Add an Annotation'),
+      'field types' => array('chado_linker__cvterm_adder'),
+    );
+  }
+  /**
+   * @see TripalField::widget_form()
+   */
+  function widget_form(&$widget, $form, $form_state, $field, $instance,
+      $langcode, $items, $delta, $element) {
+
+    // This field has no value field.  Just a fieldset for adding new annotation types.
+
+    $widget['#element_validate'] = array('chado_linker__cvterm_adder_widget_validate');
+
+    $widget['#type'] = 'fieldset';
+    $widget['#title'] = $element['#title'];
+    $widget['#description'] = $element['#description'];
+    $widget['#group'] = 'entity_form_vtabs';
+
+    $widget['cvterm_class_adder_instructions'] = array(
+      '#type' => 'item',
+      '#markup' => t('You may add annotation types to this form by
+          providing a vocabulary name in the field below
+          and clicking the "Add Annotation Type" button.  This will add a
+          new field to the form above for the vocabulary you entered which
+          will allow users to associate terms from that vocabulary to
+          this record.'),
+    );
+
+    $options = tripal_get_cv_select_options();
+    $widget['value'] = array(
+      '#type' => 'select',
+      '#title' => t('Vocabulary'),
+      '#options' => $options,
+      '#description' => t("Please enter the vocabulary that contains terms
+          you want to allow users to use for annotations."),
+    );
+
+    // When this button is clicked, the form will be validated and submitted.
+    // Therefore, we set custom submit and validate functions to override the
+    // default form submit.  In the validate function we set the form_state
+    // to rebuild the form so the submit function never actually gets called,
+    // but we need it or Drupal will run the default validate anyway.
+    // we also set #limit_validation_errors to empty so fields that
+    // are required that don't have values won't generate warnings.
+    $widget['cvterm_class_adder_button'] = array(
+      '#value' => t('Add Annotation Type'),
+      '#type' => 'submit',
+      '#name' => 'cvterm_class_adder_button',
+      '#submit' => array('chado_linker__cvterm_adder_widget_submit'),
+      '#limit_validation_errors' => array(array($field['field_name'])),
+    );
+  }
 
-  // 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,
-    ),
-    '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.
-  );
-
-  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__cvterm_adder_widget_info() {
-  return array(
-    'label' => t('Add an Annotation'),
-    'field types' => array('chado_linker__cvterm_adder'),
-  );
-}
-/**
- *
- */
-function chado_linker__cvterm_adder_widget(&$widget, &$form, &$form_state,
-    $field, $instance, $langcode, $items, $delta, $element) {
-
-  // This field has no value field.  Just a fieldset for adding new annotation types.
-
-  $widget['#element_validate'] = array('chado_linker__cvterm_adder_widget_validate');
-
-  $widget['#type'] = 'fieldset';
-  $widget['#title'] = $element['#title'];
-  $widget['#description'] = $element['#description'];
-  $widget['#group'] = 'entity_form_vtabs';
-
-  $widget['cvterm_class_adder_instructions'] = array(
-    '#type' => 'item',
-    '#markup' => t('You may add annotation types to this form by
-        providing a vocabulary name in the field below
-        and clicking the "Add Annotation Type" button.  This will add a
-        new field to the form above for the vocabulary you entered which
-        will allow users to associate terms from that vocabulary to
-        this record.'),
-  );
-
-  $options = tripal_get_cv_select_options();
-  $widget['value'] = array(
-    '#type' => 'select',
-    '#title' => t('Vocabulary'),
-    '#options' => $options,
-    '#description' => t("Please enter the vocabulary that contains terms
-        you want to allow users to use for annotations."),
-  );
-
-  // When this button is clicked, the form will be validated and submitted.
-  // Therefore, we set custom submit and validate functions to override the
-  // default form submit.  In the validate function we set the form_state
-  // to rebuild the form so the submit function never actually gets called,
-  // but we need it or Drupal will run the default validate anyway.
-  // we also set #limit_validation_errors to empty so fields that
-  // are required that don't have values won't generate warnings.
-  $widget['cvterm_class_adder_button'] = array(
-    '#value' => t('Add Annotation Type'),
-    '#type' => 'submit',
-    '#name' => 'cvterm_class_adder_button',
-    '#submit' => array('chado_linker__cvterm_adder_widget_submit'),
-    '#limit_validation_errors' => array(array($field['field_name'])),
-  );
 }
 /**
  * Callback function for validating the chado_linker__cvterm_adder_widget.
  */
 function chado_linker__cvterm_adder_widget_validate($element, &$form_state) {
 
-   // Add the new field to the entity
-   if (array_key_exists('triggering_element', $form_state) and
-       $form_state['triggering_element']['#name'] == 'cvterm_class_adder_button') {
-
-     $form_state['rebuild'] = TRUE;
-     $field_name = $element['#field_name'];
-     $entity_type = $element['#entity']->type;
-     $bundle = $element['#entity']->bundle;
-
-     // Get the base table name from the field annotations.
-     $field = field_info_field($field_name);
-     $base_table = $field['settings']['base_table'];
-
-     // Get the vocabulary.
-     $cvterm_class_adder = tripal_chado_get_field_form_values($field_name, $form_state);
-     $cv = chado_generate_var('cv', array('cv_id' => $cvterm_class_adder));
-
-     if (!$cv) {
-       form_set_error(implode('][', $element ['#parents']) . '][value', t("Please select a vocabulary."));
-       return;
-     }
-
-     $type_field_name = $field_name . '__' . $cv->cv_id;
-
-     // The field name is the table name in this case. We want to get the
-     // primary key as this should be the field that maps th the value.
-     $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 new field to the entity
+  if (array_key_exists('triggering_element', $form_state) and
+      $form_state['triggering_element']['#name'] == 'cvterm_class_adder_button') {
+
+    $form_state['rebuild'] = TRUE;
+    $field_name = $element['#field_name'];
+    $entity_type = $element['#entity']->type;
+    $bundle = $element['#entity']->bundle;
+
+    // Get the base table name from the field annotations.
+    $field = field_info_field($field_name);
+    $base_table = $field['settings']['base_table'];
+
+    // Get the vocabulary.
+    $cvterm_class_adder = tripal_chado_get_field_form_values($field_name, $form_state);
+    $cv = chado_generate_var('cv', array('cv_id' => $cvterm_class_adder));
+
+    if (!$cv) {
+      form_set_error(implode('][', $element ['#parents']) . '][value', t("Please select a vocabulary."));
+      return;
+    }
+
+    $type_field_name = $field_name . '__' . $cv->cv_id;
+
+    // The field name is the table name in this case. We want to get the
+    // primary key as this should be the field that maps th the value.
+    $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);
+
+  }
 }
 /**
  * Callback function for submitting the chado_linker__cvterm_adder_widget.

+ 341 - 92
tripal_chado/includes/fields/chado_linker__dbxref.inc

@@ -1,6 +1,15 @@
 <?php
 
-class chado_linker_dbxref extends TripalField {
+/**
+ * This class provides fields for adding database cross-references.
+ *
+ * It supports two types of cross-references. The primary cross reference
+ * which is usually in the base table as an FK to the dbxref table, and
+ * secondary cross references which are in a linking table that connects
+ * the base table with the dbxref table.
+ *
+ */
+class chado_linker__dbxref extends TripalField {
   /**
    * Implements hook_info() for fields.
    *
@@ -26,55 +35,64 @@ class chado_linker_dbxref extends TripalField {
   /**
    * @see TripalField::attach_info()
    */
-  function attach_info($entity_type, $bundle, $target) {
+  function attach_info($entity_type, $bundle, $settings) {
     $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'];
-
+    $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 base table has a 'dbxref_id' then we want to attach
+    $attach = FALSE;
+    $cardinality = 1;
+    $field_name = $table_name . '__dbxref_id';
+    $chado_table = $table_name;
+    $chado_column = 'dbxref_id';
+    $schema = chado_get_schema($table_name);
+    if (array_key_exists('dbxref_id', $schema['fields'])){
+      $attach = TRUE;
+    }
 
-    // If the linker table does not exists then we don't want to add attach.
+    // If the linker table exists then we want to attach.
     $dbxref_table = $table_name . '_dbxref';
-    if (!chado_table_exists($dbxref_table)) {
-      return $field_info;
+    if (chado_table_exists($dbxref_table)) {
+      $schema = chado_get_schema($dbxref_table);
+      $pkey = $schema['primary key'][0];
+      $attach = TRUE;
+      $field_name = $dbxref_table;
+      $cardinality = FIELD_CARDINALITY_UNLIMITED;
+      $chado_table = $dbxref_table;
+      $chado_column = $pkey;
     }
 
-    // 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' => '',
-      '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' => array(
-          'name' => '',
-          'accession' => '',
-          'ns' => '',
-          'nsurl' => '',
+    if ($attach) {
+      // Initialize the field array.
+      $field_info = array(
+        'field_name' => $field_name,
+        'field_type' => 'chado_linker__dbxref',
+        'widget_type' => 'chado_linker__dbxref_widget',
+        'widget_settings' => array(
+          'display_label' => 1
         ),
-      ),
-    );
-
-    // If the base table has a 'dbxref_id' then change the label to
-    // indicate these are secondary cross references.
-    $schema = chado_get_schema($table_name);
-    if (array_key_exists('dbxref_id', $schema['fields'])) {
-      $field_info['label'] = 'Secondary Cross References';
+        'description' => '',
+        'label' => 'Cross References',
+        'is_required' => 0,
+        'cardinality' => $cardinality,
+        'storage' => 'field_chado_storage',
+        'field_settings' => array(
+          'chado_table' => $chado_table,
+          'chado_column' => $chado_column,
+          'base_table' => $table_name,
+          'semantic_web' => array(
+            'name' => 'database cross reference',
+            'accession' => '0000554',
+            'ns' => 'SBO',
+            'nsurl' => 'http://www.ebi.ac.uk/sbo/main/',
+          ),
+        ),
+      );
     }
 
     return $field_info;
@@ -109,28 +127,189 @@ class chado_linker_dbxref extends TripalField {
   function formatter_view(&$element, $entity_type, $entity, $field,
       $instance, $langcode, $items, $display) {
 
-    $chado_table = $field['settings']['chado_table'];
+    dpm($items);
     foreach ($items as $delta => $item) {
-      $accession = '';
-      if ($item[$chado_table . '__dbxref_id']) {
-        $dbxref = chado_generate_var('dbxref', array('dbxref_id' => $item[$chado_table . '__dbxref_id']));
-        $accession = $dbxref->db_id->name . ':' . $dbxref->accession;
-        if ($dbxref->db_id->urlprefix) {
-          $accession = l($accession, $dbxref->db_id->urlprefix . '/' . $dbxref->accession, array('attributes' => array('target' => '_blank')));
+      if ($item['value']) {
+        $content = $item['value']['namespace'] . ':' . $item['value']['accession'];
+        if ($item['value']['URL']) {
+          $content = l($item['value']['URL'], $item['value']['URL']);
         }
+        $element[$delta] = array(
+          '#type' => 'markup',
+          '#markup' => $content,
+        );
       }
-      $element[$delta] = array(
-        '#type' => 'markup',
-        '#markup' => $accession,
-      );
     }
   }
 
+  function widget_form(&$widget, $form, $form_state, $field, $instance,
+      $langcode, $items, $delta, $element) {
+
+    $field_name = $field['field_name'];
+    $field_type = $field['type'];
+    $field_table = $field['settings']['chado_table'];
+    $field_column = $field['settings']['chado_column'];
+    dpm($items[$delta]);
+
+    $record = $element['#entity']->chado_record;
+    $base_table = $record->tablename;
+
+    // The first form element should be for the local dbxref record.
+    if (property_exists($record, 'dbxref_id') and $delta == 0) {
+      $this->base_widget_form($widget, $form, $form_state, $field, $instance,
+          $langcode, $items, $delta, $element);
+    }
+    else {
+      // The remainindg form elements should be for the linking dbxref table.
+      $this->linker_widget_form($widget, $form, $form_state, $field, $instance,
+          $langcode, $items, $delta, $element);
+    }
+  }
+
+  /**
+   * @see TripalField::widget_form()
+   */
+  private function base_widget_form(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
+    $field_name = $field['field_name'];
+    $field_type = $field['type'];
+    $base_table = $element['#entity']->chado_record->tablename;
+    $field_table = $base_table;
+    $field_column = 'dbxref_id';
+
+    // Get the field defaults.
+    $fk_val = '';
+    $dbxref_id = '';
+    $db_id = '';
+    $accession = '';
+    $version = '';
+    $description = '';
+
+    // If the field already has a value then it will come through the $items
+    // array. This happens when editing an existing record.
+    if (array_key_exists($delta, $items)) {
+      $fk_val = $items[$delta][$field_table .'__' .$field_column];
+      $dbxref_id = $items[$delta]['dbxref__dbxref_id'];
+      $db_id = $items[$delta]['dbxref__db_id'];
+      $accession = $items[$delta]['dbxref__accession'];
+      $version = $items[$delta]['dbxref__version'];
+      $description = $items[$delta]['dbxref__description'];
+    }
+
+    // Check $form_state['values'] to see if an AJAX call set the values.
+    if (array_key_exists('values', $form_state)) {
+      $fk_val = tripal_chado_get_field_form_values($field_name, $form_state, 0, $field_table .'__' .$field_column);
+      $dbxref_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, 'dbxref__dbxref_id');
+      $db_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, "dbxref__db_id");
+      $accession = tripal_chado_get_field_form_values($field_name, $form_state, 0, "dbxref__accession");
+      $version = tripal_chado_get_field_form_values($field_name, $form_state, 0, "dbxref__version");
+      $description = tripal_chado_get_field_form_values($field_name, $form_state, 0, "dbxref__description");
+    }
+
+    // If we are here because our parent was triggered in a form submit
+    // then that means an ajax call was made and we don't want the fieldset to
+    // be closed when it returns from the ajax call.
+    // $collapsed = TRUE;
+    // if (array_key_exists('triggering_element', $form_state) and
+    // $form_state['triggering_element']['#parents'][0] == $field_name) {
+    // $collapsed = FALSE;
+    // }
+    // if ($dbxref_id) {
+    // $collapsed = FALSE;
+    // }
+
+    $schema = chado_get_schema('dbxref');
+    $options = tripal_get_db_select_options();
+
+    $widget['#element_validate'] = array('chado_base__dbxref_id_widget_validate');
+    $widget['#theme'] = 'chado_base__dbxref_id_widget';
+    $widget['#prefix'] = "<span id='$field_name-dbxref--db-id'>";
+    $widget['#suffix'] = "</span>";
+
+    // A temporary element used for theming the fieldset.
+    $widget['#theme_settings'] = array(
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#theme' => 'chado_base__dbxref_id_widget'
+      // '#collapsible' => TRUE,
+      // '#collapsed' => $collapsed,
+    );
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[0]['value']
+    );
+
+    $widget[$field_table .'__' .$field_column] = array(
+      '#type' => 'value',
+      '#default_value' => $fk_val
+
+    );
+
+    $widget['dbxref__dbxref_id'] = array(
+      '#type' => 'value',
+      '#default_value' => $dbxref_id
+
+    );
+
+    $widget['dbxref__db_id'] = array(
+      '#type' => 'select',
+      '#title' => t('Database'),
+      '#options' => $options,
+      '#required' => $element['#required'],
+      '#default_value' => $db_id,
+      '#ajax' => array(
+        'callback' => "chado_base__dbxref_id_widget_form_ajax_callback",
+        'wrapper' => "$field_name-dbxref--db-id",
+        'effect' => 'fade',
+        'method' => 'replace')
+
+    );
+    $widget['dbxref__accession'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Accession'),
+      '#default_value' => $accession,
+      '#required' => $element['#required'],
+      '#maxlength' => array_key_exists('length', $schema['fields']['accession']) ? $schema['fields']['accession']['length'] : 255,
+      '#size' => 15,
+      '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/dbxref/' .$db_id,
+      '#ajax' => array(
+        'callback' => "tripal_chado_dbxref_widget_form_ajax_callback",
+        'wrapper' => "$field_name-dbxref--db-id",
+        'effect' => 'fade','method' => 'replace'
+      ),
+      '#disabled' => $db_id ? FALSE : TRUE
+
+    );
+    $widget['dbxref__version'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Version'),
+      '#default_value' => $version,
+      '#maxlength' => array_key_exists(
+        'length', $schema['fields']['version']) ? $schema['fields']['version']['length'] : 255,
+      '#size' => 5,
+      '#disabled' => $db_id ? FALSE : TRUE
+
+    );
+    $widget['dbxref__description'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Description'),
+      '#default_value' => $description,
+      '#size' => 20,
+      '#disabled' => $db_id ? FALSE : TRUE
+
+    );
+    // $widget['links'] = array(
+    // '#type' => 'item',
+    // '#markup' => l('Add a new database', 'admin/tripal/chado/tripal_db/add', array('attributes' => array('target' => '_blank')))
+    // );
+  }
+
   /**
    * @see TripalField::widget_form()
    */
-  function widget_form(&$widget, $form, $form_state, $field,
-      $instance, $langcode, $items, $delta, $element) {
+  private function linker_widget_form(&$widget, $form, $form_state, $field, $instance,
+      $langcode, $items, $delta, $element) {
 
     $field_name = $field['field_name'];
     $field_type = $field['type'];
@@ -188,9 +367,9 @@ class chado_linker_dbxref extends TripalField {
     $widget['#suffix'] =  "</span>";
 
 
-    $form['value'] = array(
+    $widget['value'] = array(
       '#type' => 'value',
-      '#value' => $items[$delta]['value'],
+      '#value' => array_key_exists($delta, $items)? $items[$delta]['value'] : '',
     );
 
     $widget[$field_table . '__' . $pkey] = array(
@@ -261,10 +440,6 @@ class chado_linker_dbxref extends TripalField {
     }
   }
 
-
-
-
-
   /**
    * @see TripalField::load()
    */
@@ -274,50 +449,97 @@ class chado_linker_dbxref extends TripalField {
 
     $field_name = $field['field_name'];
     $field_type = $field['type'];
-    $chado_table = $field['settings']['chado_table'];
-    $schema = chado_get_schema($chado_table);
+    $field_table = $field['settings']['chado_table'];
+    $field_column = $field['settings']['chado_column'];
+    $base_table = $record->tablename;
+
+    $num_dbxrefs = 0;
+
+    // Set some defauls for the empty record
+    if (property_exists($record, 'dbxref_id')) {
+      $entity->{$field_name}['und'][0] = array(
+        'value' => array(),
+        $base_table . '__dbxref_id' => '',
+        'dbxref__dbxref_id' => '',
+        'dbxref__db_id' => '',
+        'dbxref__accession' => '',
+        'dbxref__version' => '',
+        'dbxref__description' => '',
+      );
+    }
+    else {
+      $entity->{$field_name}['und'][0] = array(
+        'value' => array(),
+        $field_table . '__' . $pkey => '',
+        $field_table . '__' . $fkey => '',
+        $field_table . '__' . 'dbxref_id' => '',
+        $field_table . '--' . 'dbxref__dbxref_id' => '',
+        $field_table . '--' . 'dbxref__db_id' => '',
+        $field_table . '--' . 'dbxref__accession' => '',
+        $field_table . '--' . 'dbxref__version' => '',
+        $field_table . '--' . 'dbxref__description' => '',
+      );
+    }
+
+    // First check to see if a local dbxref_id field has values, if it does
+    // then add it.
+    if (property_exists($record, 'dbxref_id')) {
+      $dbxref = $record->dbxref_id;
+      $value = $dbxref->db_id->name . ':' . $dbxref->accession;
+      $URL = '';
+      if ($dbxref->db_id->urlprefix) {
+        $URL = l($value, $dbxref->db_id->urlprefix . '/' . $dbxref->accession);
+      }
+
+      $entity->{$field_name}['und'][$num_dbxrefs] = array(
+        'value' => array(
+          'namespace' => $dbxref->db_id->name,
+          'accession' => $dbxref->accession,
+          'URL' => $URL,
+        ),
+        $base_table . '__dbxref_id' => $dbxref->dbxref_id,
+        'dbxref__dbxref_id' => $dbxref->dbxref_id,
+        'dbxref__db_id' => $dbxref->db_id->db_id,
+        'dbxref__accession' => $dbxref->accession,
+        'dbxref__version' => $dbxref->version,
+        'dbxref__description' => $dbxref->description,
+      );
+      $num_dbxrefs++;
+    }
+
+    // Second, check in the dbxref linker table for values.
+    $schema = chado_get_schema($field_table);
     $pkey = $schema['primary key'][0];
     $fkeys = array_values($schema['foreign keys'][$base_table]['columns']);
     $fkey = $fkeys[0];
-
-    // Set some defaults for the empty record.
-    $entity->{$field_name}['und'][0] = array(
-      'value' => '',
-      $chado_table . '__' . $pkey => '',
-      $chado_table . '__' . $fkey => '',
-      $chado_table . '__' . 'dbxref_id' => '',
-      $chado_table . '--' . 'dbxref__dbxref_id' => '',
-      $chado_table . '--' . 'dbxref__db_id' => '',
-      $chado_table . '--' . 'dbxref__accession' => '',
-      $chado_table . '--' . 'dbxref__version' => '',
-      $chado_table . '--' . 'dbxref__description' => '',
-    );
-
     $linker_table = $base_table . '_dbxref';
     $options = array('return_array' => 1);
     $record = chado_expand_var($record, 'table', $linker_table, $options);
     if (count($record->$linker_table) > 0) {
-      $i = 0;
       foreach ($record->$linker_table as $index => $linker) {
         $dbxref = $linker->dbxref_id;
-        $entity->{$field_name}['und'][$i] = array(
-          'value' => array(),
-          $chado_table . '__' . $pkey => $linker->$pkey,
-          $chado_table . '__' . $fkey => $linker->$fkey->$fkey,
-          $chado_table . '__' . 'dbxref_id' => $dbxref->dbxref_id,
-          $chado_table . '--' . 'dbxref__dbxref_id' => $dbxref->dbxref_id,
-          $chado_table . '--' . 'dbxref__db_id' => $dbxref->db_id->db_id,
-          $chado_table . '--' . 'dbxref__accession' => $dbxref->accession,
-          $chado_table . '--' . 'dbxref__version' => $dbxref->version,
-          $chado_table . '--' . 'dbxref__description' => $dbxref->description,
+        $entity->{$field_name}['und'][$num_dbxrefs] = array(
+          'value' => array(
+            'namespace' => $dbxref->db_id->name,
+            'accession' => $dbxref->accession,
+            'URL' => $URL,
+          ),
+          $field_table . '__' . $pkey => $linker->$pkey,
+          $field_table . '__' . $fkey => $linker->$fkey->$fkey,
+          $field_table . '__' . 'dbxref_id' => $dbxref->dbxref_id,
+          $field_table . '--' . 'dbxref__dbxref_id' => $dbxref->dbxref_id,
+          $field_table . '--' . 'dbxref__db_id' => $dbxref->db_id->db_id,
+          $field_table . '--' . 'dbxref__accession' => $dbxref->accession,
+          $field_table . '--' . 'dbxref__version' => $dbxref->version,
+          $field_table . '--' . 'dbxref__description' => $dbxref->description,
         );
-        $i++;
+        $num_dbxrefs++;
       }
     }
   }
 }
 /**
- * Theme function for the dbxref_id_widget.
+ * Theme function for the linker table dbxrefs.
  *
  * @param $variables
  */
@@ -330,7 +552,7 @@ function theme_chado_linker__dbxref_widget($variables) {
   $fkey = $element['#fkey_field'];
 
   $layout = "
-      <div class=\"secondary-dbxref-widget\">
+      <div>
         <div class=\"secondary-dbxref-widget-item\">" .
         drupal_render($element[$table_name . '--dbxref__db_id']) . "
         </div>
@@ -434,4 +656,31 @@ function chado_linker__dbxref_widget_form_ajax_callback($form, $form_state) {
   }
 
   return $form[$field_name]['und'][$delta];
+}
+
+/**
+ * Theme function for the local base table dbxrefs.
+ */
+function theme_chado_base__dbxref_id_widget($variables) {
+  $element = $variables['element'];
+
+  $layout = "
+      <div>
+        <div class=\"primary-dbxref-widget-item\">" .
+        drupal_render($element['dbxref__db_id']) . "
+        </div>
+        <div class=\"primary-dbxref-widget-item\">" .
+        drupal_render($element['dbxref__accession']) . "
+        </div>
+        <div class=\"primary-dbxref-widget-item\">" .
+        drupal_render($element['dbxref__version']) . "
+        </div>
+        <div class=\"primary-dbxref-widget-item\">" .
+        drupal_render($element['dbxref__description']) . "
+        </div>
+        <div class=\"primary-dbxref-widget-links\">" . drupal_render($element['links']) . "</div>
+      </div>
+    ";
+
+  return $layout;
 }

+ 3 - 5
tripal_chado/includes/fields/chado_linker__expression.inc

@@ -52,7 +52,7 @@ class chado_linker__expression extends TripalField {
 
     // Initialize the field array.
     $field_info = array(
-      'field_name' => $table_name . '__expression',
+      'field_name' => $table_name . '_expression',
       'field_type' => 'chado_linker__expression',
       'widget_type' => 'chado_linker__expression_widget',
       'widget_settings' => array('display_label' => 1),
@@ -160,10 +160,8 @@ class chado_linker__expression extends TripalField {
 
   public function widget_form(&$widget, $form, $form_state, $field, $instance,
       $langcode, $items, $delta, $element) {
-    $form['value'] = array(
-      '#type' => 'value',
-      '#value' => $items[$delta]['value'],
-    );
+
+
   }
 
   public function load($field, $entity, $details) {

+ 1 - 4
tripal_chado/includes/fields/chado_linker__featureloc.inc

@@ -356,10 +356,7 @@ class chado_linker__featureloc extends TripalField {
    * @see TripalField::widget_form()
    */
   function widget_form(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-    $form['value'] = array(
-      '#type' => 'value',
-      '#value' => $items[$delta]['value'],
-    );
+
   }
 
 }

+ 1 - 1
tripal_chado/includes/fields/chado_linker__prop.inc

@@ -154,7 +154,7 @@ function chado_linker__prop_widget(&$widget, $form, $form_state, $field, $instan
   $widget['#element_validate'] = array('chado_linker__prop_widget_validate');
   $widget['#cardinality'] = 1;
 
-  $form['value'] = array(
+  $widget['value'] = array(
     '#type' => 'value',
     '#value' => $items[$delta]['value'],
   );

+ 1 - 1
tripal_chado/includes/fields/chado_linker__pub.inc

@@ -162,7 +162,7 @@ class chado_linker_pub extends TripalField {
     $widget['#prefix'] =  "<span id='$table_name-$delta'>";
     $widget['#suffix'] =  "</span>";
 
-    $form['value'] = array(
+    $widget['value'] = array(
       '#type' => 'value',
       '#value' => $items[$delta]['value'],
     );

+ 1 - 1
tripal_chado/includes/fields/chado_linker__relationship.inc

@@ -42,7 +42,7 @@ class chado_linker__relationship extends TripalField {
 
     // Initialize the field array.
     $field_info = array(
-      'field_name' => $table_name . '__relationship',
+      'field_name' => $table_name . '_relationship',
       'field_type' => 'chado_linker__relationship',
       'widget_type' => 'chado_linker__relationship_widget',
       'widget_settings' => array('display_label' => 1),

+ 3 - 3
tripal_chado/includes/fields/chado_linker__synonym.inc

@@ -42,7 +42,7 @@ class chado_linker__synonym extends TripalField {
 
     // Initialize the field array.
     $field_info = array(
-      'field_name' => $table_name . '__synonym',
+      'field_name' => $table_name . '_synonym',
       'field_type' => 'chado_linker__synonym',
       'widget_type' => 'chado_linker__synonym_widget',
       'widget_settings' => array('display_label' => 1),
@@ -173,9 +173,9 @@ class chado_linker__synonym extends TripalField {
     $widget['#prefix'] =  "<span id='$table_name-$delta'>";
     $widget['#suffix'] =  "</span>";
 
-    $form['value'] = array(
+    $widget['value'] = array(
       '#type' => 'value',
-      '#value' => $items[$delta]['value'],
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
     );
 
     $widget[$table_name . '__' . $pkey] = array(

+ 7 - 7
tripal_chado/includes/tripal_chado.field_storage.inc

@@ -138,7 +138,7 @@ function tripal_chado_field_storage_write_recursive($entity_type, $entity, $term
       $fk_vals = array();
       $fk_field_name = $tablename . '__' . $local_id;
       if (array_key_exists($fk_field_name, $field_vals)) {
-        $fk_val = $field_vals[$fk_field_name][0][$base_table . '__' . $local_id];
+        $fk_val = $field_vals[$fk_field_name][0][$tablename . '__' . $local_id];
         $fk_vals = $field_vals[$fk_field_name][0];
       }
 
@@ -204,6 +204,7 @@ function tripal_chado_field_storage_write_recursive($entity_type, $entity, $term
     return $record_id;
   }
 
+  dpm($values);
   // If we don't have an incoming record ID then this is an insert.
   if ($record_id == NULL) {
     // STEP 3a: Before inserting, we want to make sure the record does not
@@ -396,9 +397,6 @@ function tripal_chado_field_storage_unnest_fields($fields, $entity_type, $entity
     // Iterate through the field's items. Fields with cardinality ($delta) > 1
     // are multi-valued.
     $items = field_get_items($entity_type, $entity, $field_name);
-//     if ($field_name == 'feature__organism_id') {
-//       dpm($items);
-//     }
     foreach ($items as $delta => $item) {
       foreach ($item as $item_name => $value) {
         $matches = array();
@@ -407,12 +405,14 @@ function tripal_chado_field_storage_unnest_fields($fields, $entity_type, $entity
           $new_fields[$field_name][$delta][$item_name] = $value;
         }
       }
-      // If there is no value set for the field using the [table_name]__[field name]
-      // naming schema then check if a 'value' item is present and if so use that.
+      // If there is no value set for the field using the
+      // [table_name]__[field name] naming schema then check if a 'value' item
+      // is present and if so use that.
       $item_name = $chado_table . '__' . $chado_column;
       if ((!array_key_exists($field_name, $new_fields) or
            !array_key_exists($item_name, $new_fields[$field_name][$delta])) and
-          array_key_exists('value', $items[$delta])) {
+          array_key_exists('value', $items[$delta]) and
+          !is_array($items[$delta]['value'])) {
         $new_fields[$field_name][$delta][$item_name] = $items[$delta]['value'];
       }
     }