Переглянути джерело

nightly checkin. Fixing fields so that 'values' are the delivered content rather than the Chado value to be saved

Stephen Ficklin 9 роки тому
батько
коміт
e6f7eb4a3d

+ 0 - 1
tripal/includes/TripalEntityUIController.inc

@@ -234,7 +234,6 @@ function tripal_view_entity($entity, $view_mode = 'full') {
    $result = $query->range(0, 25)
      ->addMetaData('account', $user)
      ->execute();
-   dpm($result);
 
    $headers = array('Title', 'Vocabulary', 'Term', 'Author', 'Status', 'Updated', 'Operations');
    $rows = array();

+ 22 - 0
tripal/includes/TripalField.inc

@@ -146,6 +146,13 @@ class TripalField {
    */
   public function formatter_view(&$element, $entity_type, $entity,
       $field, $instance, $langcode, $items, $display) {
+
+    foreach($items as $delta => $item) {
+      $element[$delta] = array(
+        '#type' => 'markup',
+        '#markup' => $item['value'],
+      );
+    }
   }
 
   /**
@@ -155,6 +162,17 @@ class TripalField {
    * existing entity.  If the field is attached to the entity then the form
    * provided by this function will be displayed.
    *
+   * At a minimum, the form must have a 'value' element.  For Tripal, the
+   * 'value' element of a field always corresponds to the value that is
+   * presented to the end-user either directly on the page (with formatting)
+   * or via web services, or some other mechanism.  However, the 'value' is
+   * sometimes not enough for a field.  For example, the Tripal Chado module
+   * maps fields to table columns and sometimes those columns are foreign keys
+   * therefore, the Tripal Chado modules does not use the 'value' but adds
+   * additional elements to help link records via FKs.  But even in this case
+   * the 'value' element must always be present in the returne form and in such
+   * cases it's value should be set equal to that added in the 'load' function.
+   *
    * @param $widget
    * @param $form
    * @param $form_state
@@ -171,6 +189,10 @@ class TripalField {
   public function widget_form(&$widget, $form, $form_state, $field, $instance,
       $langcode, $items, $delta, $element) {
 
+    $form['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['value'],
+    );
   }
   /**
    * Loads the field values from the underlying data store.

+ 36 - 25
tripal_chado/includes/fields/chado_base__dbxref_id.inc

@@ -60,10 +60,10 @@ class chado_base__dbxref_id extends TripalField {
         'chado_table' => $table_name,
         'chado_column' => 'dbxref_id',
         'semantic_web' => array(
-          'name' => '',
-          'accession' => '',
-          'ns' => '',
-          'nsurl' => '',
+          'name' => 'database cross reference',
+          'accession' => '0000554',
+          'ns' => 'SBO',
+          'nsurl' => 'http://www.ebi.ac.uk/sbo/main/',
         ),
       ),
     );
@@ -100,23 +100,17 @@ class chado_base__dbxref_id extends TripalField {
    */
   function formatter_view(&$element, $entity_type, $entity, $field,
       $instance, $langcode, $items, $display) {
-
-    $record = $entity->chado_record;
-
     foreach ($items as $delta => $item) {
-      $accession = '';
       if ($item['value']) {
-        $dbxref = $record->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')));
+        $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,
-      );
     }
   }
   /**
@@ -137,7 +131,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)) {
-      $dbxref_id = $items[$delta]['value'];
+      $dbxref_id = $items[$delta]['dbxref__dbxref_id'];
       $db_id = $items[$delta]['dbxref__db_id'];
       $accession = $items[$delta]['dbxref__accession'];
       $version = $items[$delta]['dbxref__version'];
@@ -146,7 +140,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)) {
-      $dbxref_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, $field_name);
+      $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");
@@ -183,7 +177,12 @@ class chado_base__dbxref_id extends TripalField {
       //'#collapsed' => $collapsed,
     );
 
-    $widget['value'] = array(
+    $form['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[0]['value'],
+    );
+
+    $widget['dbxref__dbxref_id'] = array(
       '#type' => 'value',
       '#default_value' => $dbxref_id,
     );
@@ -252,7 +251,8 @@ class chado_base__dbxref_id extends TripalField {
 
     // Set some defauls for the empty record
     $entity->{$field_name}['und'][0] = array(
-      'value' => '',
+      'value' => array(),
+      'dbxref__dbxref_id' => '',
       'dbxref__db_id' => '',
       'dbxref__accession' => '',
       'dbxref__version' => '',
@@ -267,8 +267,19 @@ class chado_base__dbxref_id extends TripalField {
       $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' => $dbxref->dbxref_id,
+          '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,
@@ -293,7 +304,7 @@ function chado_base__dbxref_id_widget_validate($element, &$form_state) {
   }
 
   // Get the field values.
-  $dbxref_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, $field_name);
+  $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");
@@ -319,7 +330,7 @@ function chado_base__dbxref_id_widget_validate($element, &$form_state) {
   // If user did not select a database, we want to remove dbxref_id from the
   // field.
   if (!$db_id) {
-    tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__');
+    tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__', 0, 'dbxref__dbxref_id');
   }
   // 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
@@ -327,7 +338,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);
+      tripal_chado_set_field_form_values($field_name, $form_state, $dbxref->dbxref_id, 0, 'dbxref__dbxref_id');
     }
   }
 }

+ 59 - 23
tripal_chado/includes/fields/chado_feature__md5checksum.inc → tripal_chado/includes/fields/chado_base__md5checksum.inc

@@ -1,6 +1,6 @@
 <?php
 
-class chado_feature__md5checksum  extends TripalField {
+class chado_base__md5checksum  extends TripalField {
 
   /**
    * @see TripalField::field_info()
@@ -9,8 +9,8 @@ class chado_feature__md5checksum  extends TripalField {
     return array(
       'label' => t('MD5 checksum'),
       'description' => t('A field for generating MD5 checksum for a sequence.'),
-      'default_widget' => 'chado_feature__md5checksum_widget',
-      'default_formatter' => 'chado_feature__md5checksum_formatter',
+      'default_widget' => 'chado_base__md5checksum_widget',
+      'default_formatter' => 'chado_base__md5checksum_formatter',
       'settings' => array(),
       'storage' => array(
         'type' => 'field_chado_storage',
@@ -32,23 +32,39 @@ class chado_feature__md5checksum  extends TripalField {
     $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') {
+    $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' => 'feature__md5checksum',
-      'field_type' => 'chado_feature__md5checksum',
-      'widget_type' => 'chado_feature__md5checksum_widget',
+      '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
+        'display_label' => 1,
+        'md5_fieldname' => $md5_fieldname,
       ),
       'field_settings' => array(
         'chado_table' => $table_name,
@@ -70,7 +86,7 @@ class chado_feature__md5checksum  extends TripalField {
   function widget_info() {
     return array(
       'label' => t('MD5 Checksum Checkbox'),
-      'field types' => array('chado_feature__md5checksum'),
+      'field types' => array('chado_base__md5checksum'),
     );
   }
 
@@ -80,7 +96,7 @@ class chado_feature__md5checksum  extends TripalField {
   function formatter_info() {
     return array(
       'label' => t('MD5 Checksum'),
-      'field types' => array('chado_feature__md5checksum'),
+      'field types' => array('chado_base__md5checksum'),
       'settings' => array(
       ),
     );
@@ -105,16 +121,26 @@ class chado_feature__md5checksum  extends TripalField {
    * @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'];
 
-    $widget['value'] = array(
+    $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' => 1,
+      '#default_value' => '',
       '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
       '#delta' => $delta,
-      '#element_validate' => array('chado_feature__md5checksum_widget_validate'),
+      '#element_validate' => array('chado_base__md5checksum_widget_validate'),
     );
   }
 
@@ -124,29 +150,39 @@ class chado_feature__md5checksum  extends TripalField {
    */
   function load($field, $entity, $details) {
     $record = $details['record'];
+    $settings = $field['settings'];
 
     $field_name = $field['field_name'];
-    if ($record and property_exists($record, 'md5checksum')) {
-      $entity->{$field_name}['und'][0]['value'] = $record->md5checksum;
-    }
+    $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_feature__md5checksum_widget.
+ * Callback function for validating the chado_base__md5checksum_widget.
  */
-function chado_feature__md5checksum_widget_validate($element, &$form_state) {
+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);
+  $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));
+    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__');
+    tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__', 0, $field_table . '__md5checksum');
   }
 }

+ 21 - 9
tripal_chado/includes/fields/chado_base__organism_id.inc

@@ -120,13 +120,23 @@ class chado_base__organism_id extends TripalField {
   public 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'];
+
     $default_value = 0;
-    if (array_key_exists('organism_id', $items[0])) {
-      $default_value = $items[0]['organism_id'];
+    if (array_key_exists($field_table . '__organism_id', $items[0])) {
+      $default_value = $items[0][$field_table . '__organism_id'];
     }
 
-    $options = tripal_get_organism_select_options(FALSE);
     $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[0]['value'],
+    );
+    $options = tripal_get_organism_select_options(FALSE);
+    $widget[$field_table . '__organism_id'] = array(
       '#type' => 'select',
       '#title' => $element['#title'],
       '#description' => $element['#description'],
@@ -137,10 +147,6 @@ class chado_base__organism_id extends TripalField {
       '#delta' => $delta,
       '#element_validate' => array('chado_base__organism_id_widget_validate'),
     );
-    $widget['add_organism'] = array(
-      '#type' => 'item',
-      '#markup' => l('Add a new species', 'admin/content/bio_data/add/species', array('attributes' => array('target' => '_blank'))),
-    );
   }
 
   /**
@@ -161,7 +167,7 @@ class chado_base__organism_id extends TripalField {
     $value = tripal_replace_chado_tokens($string, $organism);
 
     $entity->{$field_name}['und'][0]['value'] = $value;
-    $entity->{$field_name}['und'][0]['organism_id'] = $organism->organism_id;
+    $entity->{$field_name}['und'][0][$field_table . '__organism_id'] = $organism->organism_id;
 
     // Is there a published entity for this organism?
     if (property_exists($entity->chado_record->$field_column, 'entity_id')) {
@@ -248,6 +254,12 @@ class chado_base__organism_id extends TripalField {
  */
 function chado_base__organism_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
@@ -255,7 +267,7 @@ function chado_base__organism_id_widget_validate($element, &$form_state) {
   if ($form_state['build_info']['form_id'] =='field_ui_field_edit_form') {
     return;
   }
-  $organism_id = tripal_chado_get_field_form_values($field_name, $form_state);
+  $organism_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, $field_table . '__organism_id');
 
   if (!$organism_id) {
     form_error($element, t("Please specify an organism."));

+ 13 - 3
tripal_chado/includes/fields/chado_feature__residues.inc

@@ -141,8 +141,17 @@ class chado_feature__residues extends TripalField {
    * @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'];
 
-    $widget['value'] = array(
+    $form['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['value'],
+    );
+    $widget['feature__residues'] = array(
       '#type' => 'textarea',
       '#title' => $element['#title'],
       '#description' => $element['#description'],
@@ -173,13 +182,14 @@ class chado_feature__residues extends TripalField {
 
       $feature = chado_expand_var($feature,'field','feature.residues');
       if ($feature->residues) {
-        $entity->{$field_name}['und'][$num_seqs++]['value'] = array(
+        $entity->{$field_name}['und'][$num_seqs]['value'] = array(
           '@type' => 'SO:0000110',
           'type' => 'sequence_feature',
           'label' => 'Sequence',
           'defline' => tripal_get_fasta_defline($feature, '', NULL, '', strlen($feature->residues)),
           'residues' => $feature->residues,
         );
+        $entity->{$field_name}['und'][$num_seqs++]['residues'] = $feature->residues;
       }
     }
 
@@ -624,7 +634,7 @@ function chado_feature__residues_widget_validate($element, &$form_state) {
   $residues = tripal_chado_get_field_form_values($field_name, $form_state);
   if ($residues) {
     $residues = preg_replace('/\s/', '', $residues);
-    tripal_chado_set_field_form_values($field_name, $form_state, $residues);
+    tripal_chado_set_field_form_values($field_name, $form_state, $residues, 0, 'feature__residues');
   }
 }
 

+ 15 - 4
tripal_chado/includes/fields/chado_feature__seqlen.inc

@@ -139,7 +139,18 @@ function chado_feature__seqlen_formatter(&$element, $entity_type, $entity, $fiel
  */
 function chado_feature__seqlen_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
 
-  $widget['value'] =  array(
+  $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[$delta]['value'],
+  );
+
+  $widget['feature__seqlen'] =  array(
     '#type' => 'hidden',
     '#title' => $element['#title'],
     '#description' => $element['#description'],
@@ -160,10 +171,10 @@ function chado_feature__seqlen_widget_validate($element, &$form_state) {
   // Remove any white spaces.
   if ($residues) {
     $residues = preg_replace('/\s/', '', $residues);
-    tripal_chado_set_field_form_values($field_name, $form_state, strlen($residues));
+    tripal_chado_set_field_form_values($field_name, $form_state, strlen($residues), 0, 'feature__seqlen');
   }
   else {
-    // Otherwise, remove the md5 value
-    tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__');
+    // Otherwise, remove the seqlen value
+    tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__', 0, 'feature_seqlen');
   }
 }

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

@@ -218,6 +218,9 @@ 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'],
+    );
   }
 }

+ 89 - 77
tripal_chado/includes/fields/chado_linker__contact.inc

@@ -2,6 +2,9 @@
 
 class chado_linker__contact extends TripalField {
 
+  /**
+   * @see TripalField::field_info()
+   */
   public function field_info() {
     return array(
       'label' => t('Contacts'),
@@ -17,13 +20,19 @@ class chado_linker__contact extends TripalField {
       ),
     );
   }
- function widget_info() {
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
     return array(
       'label' => t('Contacts'),
       'field types' => array('chado_linker__contact'),
     );
   }
 
+  /**
+   * @see TripalField::formatter_info()
+   */
   public function formatter_info() {
     return array(
       'label' => t('Contacts'),
@@ -32,6 +41,9 @@ class chado_linker__contact extends TripalField {
       ),
     );
   }
+  /**
+   * @see TripalField::attach_info()
+   */
   public function attach_info($entity_type, $bundle, $settings) {
     $field_info = array();
 
@@ -76,71 +88,74 @@ class chado_linker__contact extends TripalField {
     return $field_info;
   }
 
-  public function formatter_settings_summary($field, $instance, $view_mode) {
-
-  }
+  /**
+   * @see TripalField::formatter_view()
+   */
+  public function formatter_view(&$element, $entity_type, $entity,
+      $field, $instance, $langcode, $items, $display) {
+    // Get the settings
+    $settings = $display['settings'];
+    $record = $entity->chado_record;
 
-  public function formatter_settings_form($field, $instance,
-      $view_mode, $form, &$form_state) {
+    $headers = array('Name', 'Description', 'Type');
+    $rows = array();
 
-  }
+    foreach ($items as $delta => $item) {
+      $contact = $item['value'];
+      if (!$contact) {
+        continue;
+      }
 
+      // Get the field values
+      $contact_name = $contact['name'];
+      $description = $contact['description'];
+      $type = $contact['type'];
 
-  public function formatter_view(&$element, $entity_type, $entity,
-      $field, $instance, $langcode, $items, $display) {
-        // Get the settings
-        $settings = $display['settings'];
-        $record = $entity->chado_record;
-
-        $headers = array('Name', 'Description', 'Type');
-        $rows = array();
-
-        foreach ($items as $delta => $item) {
-          $contact = $item['value'];
-          if (!$contact) {
-            continue;
-          }
-
-          // Get the field values
-          $contact_name = $contact['name'];
-          $description = $contact['description'];
-          $type = $contact['type'];
-
-          // Add a link i there is an entity.
-          if (array_key_exists('entity_id', $item) and $item['entity_id']) {
-            $entity_id = $item['entity_id'];
-            $contact_name = l($contact_name, "bio_data/" . $entity_id, array('attributes' => array('target' => "_blank")));
-          }
-          $rows[] = array($contact_name, $description, $type);
-        }
-        $table = array(
-          'header' => $headers,
-          'rows' => $rows,
-          'attributes' => array(
-            'id' => 'tripal_linker-table-contact-object',
-            'class' => 'tripal-data-table'
-          ),
-          'sticky' => FALSE,
-          'caption' => "",
-          'colgroups' => array(),
-          'empty' => 'No contacts available',
-        );
-        $content = theme_table($table);
+      // Add a link i there is an entity.
+      if (array_key_exists('entity_id', $item) and $item['entity_id']) {
+        $entity_id = $item['entity_id'];
+        $contact_name = l($contact_name, "bio_data/" . $entity_id, array('attributes' => array('target' => "_blank")));
+      }
+      $rows[] = array($contact_name, $description, $type);
+    }
+    $table = array(
+      'header' => $headers,
+      'rows' => $rows,
+      'attributes' => array(
+        'id' => 'tripal_linker-table-contact-object',
+        'class' => 'tripal-data-table'
+      ),
+      'sticky' => FALSE,
+      'caption' => "",
+      'colgroups' => array(),
+      'empty' => 'No contacts available',
+    );
+    $content = theme_table($table);
 
-        // once we have our table array structure defined, we call Drupal's theme_table()
-        // function to generate the table.
-        $element[$delta] = array(
-          '#type' => 'markup',
-          '#markup' => $content,
-        );
+    // once we have our table array structure defined, we call Drupal's theme_table()
+    // function to generate the table.
+    $element[$delta] = array(
+      '#type' => 'markup',
+      '#markup' => $content,
+    );
   }
 
 
+  /**
+   * @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'],
+    );
   }
 
+  /**
+   * @see TripalField::load()
+   */
   public function load($field, $entity, $details) {
     $record = $details['record'];
     $field_name = $field['field_name'];
@@ -155,6 +170,16 @@ class chado_linker__contact extends TripalField {
     $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' => array(),
+      $field_table . '__' . $pkey => '',
+      $field_table . '__' . $fkey_lcolumn => '',
+      $field_table . '__' . 'contact_id' => '',
+      // Ignore the synonym_sgml column for now.
+    );
+
     $linker_table = $base_table . '_contact';
     $options = array(
       'return_array' => 1,
@@ -166,6 +191,7 @@ class chado_linker__contact extends TripalField {
             ),
           ),
         ),
+        $fkey_lcolumn => TRUE,
       ),
     );
     $record = chado_expand_var($record, 'table', $linker_table, $options);
@@ -173,13 +199,17 @@ class chado_linker__contact extends TripalField {
     if ($contact_linkers) {
       foreach ($contact_linkers as $i => $contact_linker) {
         $contact = $contact_linker->contact_id;
-        $entity->{$field_name}['und'][$i]['value'] = array(
-          '@type' => $contact->type_id->dbxref_id->db_id->name . ':' . $contact->type_id->dbxref_id->accession,
-          'type' => $contact->type_id->name,
-          'name' => $contact->name,
-          'description' => $contact->description,
+        $entity->{$field_name}['und'][$i] = array(
+          'value' => array(
+            '@type' => $contact->type_id->dbxref_id->db_id->name . ':' . $contact->type_id->dbxref_id->accession,
+            'type' => $contact->type_id->name,
+            'name' => $contact->name,
+            'description' => $contact->description,
+          ),
+          $field_table . '__' . $pkey => $contact_linker->$pkey,
+          $field_table . '__' . $fkey_lcolumn => $contact_linker->$fkey_lcolumn->$fkey_lcolumn,
+          $field_table . '__' . 'contact_id' => $contact->contact_id
         );
-        $entity->{$field_name}['und'][$i]['contact_id'] = $contact->contact_id;
 
         if (property_exists($contact, 'entity_id')) {
           $entity->{$field_name}['und'][$i]['entity_id'] = $contact->entity_id;
@@ -187,23 +217,5 @@ class chado_linker__contact extends TripalField {
         }
       }
     }
-
   }
-
-  /**
-   * @see TripalField::settings_form()
-   */
-  public function settings_form($field, $instance, $has_data) {
-    $element = array();
-
-    // TODO: add settings here.
-
-    // Add in the semantic web fields.
-    $parent_elements = parent::settings_form($field, $instance, $has_data);
-    $element = array_merge($element, $parent_elements);
-
-    return $element;
-  }
-
-
 }

+ 6 - 1
tripal_chado/includes/fields/chado_linker__cvterm.inc

@@ -213,7 +213,12 @@ function chado_linker__cvterm_widget(&$widget, $form, $form_state, $field,
   $widget['#prefix'] =  "<span id='$table_name-$delta'>";
   $widget['#suffix'] =  "</span>";
 
-  $widget['value'] = array(
+  $form['value'] = array(
+    '#type' => 'value',
+    '#value' => $items[$delta]['value'],
+  );
+
+  $widget[$table_name . '__' . $pkey] = array(
     '#type' => 'value',
     '#default_value' => $record_id,
   );

+ 347 - 372
tripal_chado/includes/fields/chado_linker__dbxref.inc

@@ -1,315 +1,354 @@
 <?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__dbxref_info() {
-  return array(
-    'label' => t('Cross references'),
-    'description' => t('This record can be cross referenced with a record in
-        another online database. This field is intended for one or more
-        references.  At a minimum, the database and accession must be provided.'),
-    'default_widget' => 'chado_linker__dbxref_widget',
-    'default_formatter' => 'chado_linker__dbxref_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__dbxref_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_dbxref extends TripalField {
+  /**
+   * Implements hook_info() for fields.
+   *
+   * This is a hook provided by the tripal_chado module for offloading the
+   * hook_field_info() hook for each field to specify.
+   */
+  function field_info() {
+    return array(
+      'label' => t('Cross references'),
+      'description' => t('This record can be cross referenced with a record in
+          another online database. This field is intended for one or more
+          references.  At a minimum, the database and accession must be provided.'),
+      'default_widget' => 'chado_linker__dbxref_widget',
+      'default_formatter' => 'chado_linker__dbxref_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();
+
+    $table_name = $target['data_table'];
+    $type_table = $target['type_table'];
+    $type_field = $target['field'];
+    $cv_id      = $target['cv_id'];
+    $cvterm_id  = $target['cvterm_id'];
+
+
+    // If the linker table does not exists then we don't want to add attach.
+    $dbxref_table = $table_name . '_dbxref';
+    if (!chado_table_exists($dbxref_table)) {
+      return $field_info;
+    }
+
+    // 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 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';
+    }
 
-  // If the linker table does not exists then we don't want to add attach.
-  $dbxref_table = $table_name . '_dbxref';
-  if (!chado_table_exists($dbxref_table)) {
     return $field_info;
   }
-
-  // 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' => '',
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('Cross references'),
+      'field types' => array('chado_linker__dbxref'),
+      'description' => t('This record can be cross referenced with a record
+          in another online database. This field is intended for the most
+          prominent reference.  At a minimum, the database and accession
+          must be provided.'),
+    );
+  }
+  /**
+   * @see TripalField::formatter_info()
+   */
+  function formatter_info() {
+    return array(
+      'label' => t('Cross references'),
+      'field types' => array('chado_linker__dbxref'),
+      'settings' => array(
       ),
-    ),
-  );
-
-  // 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';
+    );
+  }
+  /**
+   * @see TripalField::formatter_view()
+   */
+  function formatter_view(&$element, $entity_type, $entity, $field,
+      $instance, $langcode, $items, $display) {
+
+    $chado_table = $field['settings']['chado_table'];
+    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')));
+        }
+      }
+      $element[$delta] = array(
+        '#type' => 'markup',
+        '#markup' => $accession,
+      );
+    }
   }
 
-  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__dbxref_widget_info() {
-  return array(
-    'label' => t('Cross references'),
-    'field types' => array('chado_linker__dbxref'),
-    'description' => t('This record can be cross referenced with a record
-        in another online database. This field is intended for the most
-        prominent reference.  At a minimum, the database and accession
-        must be provided.'),
-  );
-}
-/**
- * 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__dbxref_formatter_info() {
-  return array(
-    'label' => t('Cross references'),
-    'field types' => array('chado_linker__dbxref'),
-    '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__dbxref_formatter(&$element, $entity_type, $entity, $field,
-    $instance, $langcode, $items, $display) {
-
-  $chado_table = $field['settings']['chado_table'];
-  foreach ($items as $delta => $item) {
+  /**
+   * @see TripalField::widget_form()
+   */
+  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'];
+
+    // 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 = '';
+    $dbxref_id = '';
+    $db_id = '';
     $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')));
-      }
+    $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)) {
+      $record_id = $items[$delta]['value'];
+      $fkey_value = $items[$delta][$field_name . '__' . $fkey];
+      $dbxref_id = $items[$delta][$field_name . '__dbxref_id'];
+      $db_id = $items[$delta][$field_name . '--dbxref__db_id'];
+      $accession = $items[$delta][$field_name . '--dbxref__accession'];
+      $version = $items[$delta][$field_name . '--dbxref__version'];
+      $description = $items[$delta][$field_name . '--dbxref__description'];
     }
-    $element[$delta] = array(
-      '#type' => 'markup',
-      '#markup' => $accession,
+
+    // 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($field_name, $form_state, $delta, $field_name);
+      $fkey_value = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '__' . $fkey);
+      $dbxref_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '__dbxref_id');
+      $db_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__db_id');
+      $accession = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__accession');
+      $version = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__version');
+      $description = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__description');
+    }
+
+    $schema = chado_get_schema('dbxref');
+    $options = tripal_get_db_select_options();
+
+    $widget['#table_name'] = $chado_table;
+    $widget['#fkey_field'] = $fkey;
+    $widget['#element_validate'] = array('chado_linker__dbxref_widget_validate');
+    $widget['#theme'] = 'chado_linker__dbxref_widget';
+    $widget['#prefix'] =  "<span id='$field_name-dbxref--db-id-$delta'>";
+    $widget['#suffix'] =  "</span>";
+
+
+    $form['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['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_linker__dbxref_widget(&$widget, $form, $form_state, $field,
-    $instance, $langcode, $items, $delta, $element) {
-
-  $field_name = $field['field_name'];
-
-  // 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 = '';
-  $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)) {
-    $record_id = $items[$delta]['value'];
-    $fkey_value = $items[$delta][$field_name . '__' . $fkey];
-    $dbxref_id = $items[$delta][$field_name . '__dbxref_id'];
-    $db_id = $items[$delta][$field_name . '--dbxref__db_id'];
-    $accession = $items[$delta][$field_name . '--dbxref__accession'];
-    $version = $items[$delta][$field_name . '--dbxref__version'];
-    $description = $items[$delta][$field_name . '--dbxref__description'];
-  }
 
-  // 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($field_name, $form_state, $delta, $field_name);
-    $fkey_value = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '__' . $fkey);
-    $dbxref_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '__dbxref_id');
-    $db_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__db_id');
-    $accession = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__accession');
-    $version = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__version');
-    $description = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__description');
+    $widget[$field_table . '__' . $pkey] = array(
+      '#type' => 'value',
+      '#default_value' => $record_id,
+    );
+    $widget[$field_table . '__dbxref_id'] = array(
+      '#type' => 'value',
+      '#default_value' => $dbxref_id,
+    );
+    $widget[$field_table . '__' . $fkey] = array(
+      '#type' => 'value',
+      '#default_value' => $fkey_value,
+    );
+    $widget[$field_table . '--dbxref__dbxref_id'] = array(
+      '#type' => 'value',
+      '#default_value' => $dbxref_id,
+    );
+    $widget[$field_table . '--dbxref__db_id'] = array(
+      '#type' => 'select',
+      '#title' => t('Database'),
+      '#options' => $options,
+      '#required' => $element['#required'],
+      '#default_value' => $db_id,
+      '#ajax' => array(
+        'callback' => "chado_linker__dbxref_widget_form_ajax_callback",
+        'wrapper' => "$field_name-dbxref--db-id-$delta",
+        'effect' => 'fade',
+        'method' => 'replace'
+      ),
+    );
+    $widget[$field_table . '--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' => "chado_linker__dbxref_widget_form_ajax_callback",
+        'wrapper' => "$field_name-dbxref--db-id-$delta",
+        'effect' => 'fade',
+        'method' => 'replace'
+      ),
+      '#disabled' => $db_id ? FALSE : TRUE,
+    );
+    $widget[$field_table . '--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[$field_table . '--dbxref__description'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Description'),
+      '#default_value' => $description,
+      '#size' => 20,
+      '#disabled' => $db_id ? FALSE : TRUE,
+    );
+    if (!$db_id) {
+      $widget['links'] = array(
+        '#type' => 'item',
+        '#markup' => l('Add a database', 'admin/tripal/chado/tripal_db/add', array('attributes' => array('target' => '_blank')))
+      );
+    }
   }
 
-  $schema = chado_get_schema('dbxref');
-  $options = tripal_get_db_select_options();
-
-  $widget['#table_name'] = $chado_table;
-  $widget['#fkey_field'] = $fkey;
-  $widget['#element_validate'] = array('chado_linker__dbxref_widget_validate');
-  $widget['#theme'] = 'chado_linker__dbxref_widget';
-  $widget['#prefix'] =  "<span id='$field_name-dbxref--db-id-$delta'>";
-  $widget['#suffix'] =  "</span>";
-
-  $widget['value'] = array(
-    '#type' => 'value',
-    '#default_value' => $record_id,
-  );
-  $widget[$field_name . '__dbxref_id'] = array(
-    '#type' => 'value',
-    '#default_value' => $dbxref_id,
-  );
-  $widget[$field_name . '__' . $fkey] = array(
-    '#type' => 'value',
-    '#default_value' => $fkey_value,
-  );
-  $widget[$field_name . '--dbxref__dbxref_id'] = array(
-    '#type' => 'value',
-    '#default_value' => $dbxref_id,
-  );
-  $widget[$field_name . '--dbxref__db_id'] = array(
-    '#type' => 'select',
-    '#title' => t('Database'),
-    '#options' => $options,
-    '#required' => $element['#required'],
-    '#default_value' => $db_id,
-    '#ajax' => array(
-      'callback' => "chado_linker__dbxref_widget_form_ajax_callback",
-      'wrapper' => "$field_name-dbxref--db-id-$delta",
-      'effect' => 'fade',
-      'method' => 'replace'
-    ),
-  );
-  $widget[$field_name . '--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' => "chado_linker__dbxref_widget_form_ajax_callback",
-      'wrapper' => "$field_name-dbxref--db-id-$delta",
-      'effect' => 'fade',
-      'method' => 'replace'
-    ),
-    '#disabled' => $db_id ? FALSE : TRUE,
-  );
-  $widget[$field_name . '--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[$field_name . '--dbxref__description'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Description'),
-    '#default_value' => $description,
-    '#size' => 20,
-    '#disabled' => $db_id ? FALSE : TRUE,
-  );
-  if (!$db_id) {
-    $widget['links'] = array(
-      '#type' => 'item',
-      '#markup' => l('Add a database', 'admin/tripal/chado/tripal_db/add', array('attributes' => array('target' => '_blank')))
+
+
+
+
+  /**
+   * @see TripalField::load()
+   */
+  function load($field, $entity, $details) {
+
+    $record = $details['record'];
+
+    $field_name = $field['field_name'];
+    $field_type = $field['type'];
+    $chado_table = $field['settings']['chado_table'];
+    $schema = chado_get_schema($chado_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,
+        );
+        $i++;
+      }
+    }
   }
 }
 /**
- * An Ajax callback for the dbxref widget.
+ * Theme function for the dbxref_id_widget.
+ *
+ * @param $variables
  */
-function chado_linker__dbxref_widget_form_ajax_callback($form, $form_state) {
+function theme_chado_linker__dbxref_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'];
 
-  // Check to see if this dbxref already exists. If not then
-  // give a notice to the user that the dbxref will be added.
-  $db_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__db_id');
-  $accession = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__accession');
-  if ($db_id and $accession) {
-    $values = array(
-      'db_id' => $db_id,
-      'accession' => $accession,
-    );
-    $options = array('is_duplicate' => TRUE);
-    $has_duplicate = chado_select_record('dbxref', array('*'), $values, $options);
-    if (!$has_duplicate) {
-      drupal_set_message('The selected cross reference is new and will be added for future auto completions.');
-    }
-  }
+  $layout = "
+      <div class=\"secondary-dbxref-widget\">
+        <div class=\"secondary-dbxref-widget-item\">" .
+        drupal_render($element[$table_name . '--dbxref__db_id']) . "
+        </div>
+        <div class=\"secondary-dbxref-widget-item\">" .
+        drupal_render($element[$table_name . '--dbxref__accession']) . "
+        </div>
+        <div class=\"secondary-dbxref-widget-item\">" .
+        drupal_render($element[$table_name . '--dbxref__version']) . "
+        </div>
+        <div class=\"secondary-dbxref-widget-item\">" .
+        drupal_render($element[$table_name . '--dbxref__description']) . "
+        </div>
+        <div class=\"secondary-dbxref-widget-links\">" . drupal_render($element['links']) . "</div>
+      </div>
+    ";
 
-  return $form[$field_name]['und'][$delta];
+  return $layout;
 }
-
 /**
  * Callback function for validating the chado_linker__dbxref_widget.
  */
@@ -363,100 +402,36 @@ function chado_linker__dbxref_widget_validate($element, &$form_state) {
       tripal_chado_set_field_form_values($field_name, $form_state, $dbxref->dbxref_id, $delta, $table_name . '__dbxref_id');
       tripal_chado_set_field_form_values($field_name, $form_state, $dbxref->dbxref_id, $delta, $table_name . '--dbxref__dbxref_id');
     }
-
   }
   else {
     // If the db_id and accession are not set, then remove the linker FK value to the base table.
     tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__' . $fkey);
   }
 }
+
 /**
- * Theme function for the dbxref_id_widget.
- *
- * @param $variables
+ * An Ajax callback for the dbxref widget.
  */
-function theme_chado_linker__dbxref_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=\"secondary-dbxref-widget\">
-      <div class=\"secondary-dbxref-widget-item\">" .
-        drupal_render($element[$table_name . '--dbxref__db_id']) . "
-      </div>
-      <div class=\"secondary-dbxref-widget-item\">" .
-        drupal_render($element[$table_name . '--dbxref__accession']) . "
-      </div>
-      <div class=\"secondary-dbxref-widget-item\">" .
-        drupal_render($element[$table_name . '--dbxref__version']) . "
-      </div>
-      <div class=\"secondary-dbxref-widget-item\">" .
-        drupal_render($element[$table_name . '--dbxref__description']) . "
-      </div>
-      <div class=\"secondary-dbxref-widget-links\">" . drupal_render($element['links']) . "</div>
-    </div>
-  ";
+function chado_linker__dbxref_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__dbxref_load($field, $entity, $base_table, $record) {
-
-  $field_name = $field['field_name'];
-  $field_type = $field['type'];
-  $chado_table = $field['settings']['chado_table'];
-  $schema = chado_get_schema($chado_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 . '__' . $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' => $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,
-      );
-      $i++;
+  // Check to see if this dbxref already exists. If not then
+  // give a notice to the user that the dbxref will be added.
+  $db_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__db_id');
+  $accession = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_name . '--dbxref__accession');
+  if ($db_id and $accession) {
+    $values = array(
+      'db_id' => $db_id,
+      'accession' => $accession,
+    );
+    $options = array('is_duplicate' => TRUE);
+    $has_duplicate = chado_select_record('dbxref', array('*'), $values, $options);
+    if (!$has_duplicate) {
+      drupal_set_message('The selected cross reference is new and will be added for future auto completions.');
     }
   }
+
+  return $form[$field_name]['und'][$delta];
 }

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

@@ -160,7 +160,10 @@ 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) {
@@ -212,7 +215,7 @@ class chado_linker__expression extends TripalField {
             $entity->{$field_name}['und'][$i]['publication'][0]['entity_type'] = 'TripalEntity';
           }
         }
-        
+
         // Add the linker_expressionprop
         $linkerprop_table =  $linker_table . 'prop';
         if (db_table_exists('chado.' . $linkerprop_table)) {

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

@@ -356,7 +356,10 @@ 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'],
+    );
   }
 
 }

+ 9 - 3
tripal_chado/includes/fields/chado_linker__prop.inc

@@ -154,7 +154,12 @@ function chado_linker__prop_widget(&$widget, $form, $form_state, $field, $instan
   $widget['#element_validate'] = array('chado_linker__prop_widget_validate');
   $widget['#cardinality'] = 1;
 
-  $widget['value'] = array(
+  $form['value'] = array(
+    '#type' => 'value',
+    '#value' => $items[$delta]['value'],
+  );
+
+  $widget[$table_name . '__' . $pkey] = array(
     '#type' => 'hidden',
     '#default_value' => !empty($items[$delta]['value']) ? $items[$delta]['value'] : '',
   );
@@ -219,7 +224,6 @@ function chado_linker__prop_widget_validate($element, &$form_state) {
   $type_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $table_name . '__type_id');
 
   if (!$prop_value) {
-    tripal_chado_set_field_form_values($field_name, $form_state, '', $delta);
     tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__' . $lfkey_field);
     tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__value');
     tripal_chado_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__type_id');
@@ -278,6 +282,7 @@ function chado_linker__prop_load($field, $entity, $base_table, $record) {
   // Set some defaults for the empty record.
   $entity->{$field_name}['und'][0] = array(
     'value' => '',
+    $field_table . '__' . $pkey => '',
     $field_table . '__' . $fkey_lcolumn => '',
     $field_table . '__value' => '',
     $field_table . '__type_id' => '',
@@ -300,7 +305,8 @@ function chado_linker__prop_load($field, $entity, $base_table, $record) {
     $property = $properties[$i];
     foreach ($schema['fields'] as $fname => $details) {
       $entity->{$field_name}['und'][$i] = array(
-        'value' => $property->$pkey,
+        'value' => array(),
+        $field_table . '__' . $pkey => $property->$pkey,
         $field_table . '__' . $fkey_lcolumn => $property->$fkey_lcolumn,
         $field_table . '__value' => $property->value,
         $field_table . '__type_id' => $property->type_id,

+ 256 - 286
tripal_chado/includes/fields/chado_linker__pub.inc

@@ -1,239 +1,255 @@
 <?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__pub_info() {
-  return array(
-    'label' => t('Publications'),
-    'description' => t('Associates a publication (e.g. journal article,
-          conference proceedings, book chapter, etc.) with this record.'),
-    'default_widget' => 'chado_linker__pub_widget',
-    'default_formatter' => 'chado_linker__pub_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__pub_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'];
-
-  // If the linker table does not exists then we don't want to add attach.
-  $pub_table = $table_name . '_pub';
-  if (!chado_table_exists($pub_table)) {
-    return $field_info;
-  }
 
-  $schema = chado_get_schema($pub_table);
-  $pkey = $schema['primary key'][0];
-
-  // Initialize the field array.
-  $field_info = array(
-    'field_name' => $table_name . '__pub',
-    'field_type' => 'chado_linker__pub',
-    'widget_type' => 'chado_linker__pub_widget',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Publications',
-    'is_required' => 0,
-    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-    'storage' => 'field_chado_storage',
-    'field_settings' => array(
-      'chado_table' => $pub_table,
-      'chado_column' => $pkey,
-      'base_table' => $table_name,
-      'semantic_web' => array(
-        'name' => 'publication',
-        'accession' => 'publication',
-        'ns' => 'schema',
-        'nsurl' => 'https://schema.org/',
+class chado_linker_pub extends TripalField {
+  /**
+   * @see TripalField::field_info()
+   */
+  function field_info() {
+    return array(
+      'label' => t('Publications'),
+      'description' => t('Associates a publication (e.g. journal article,
+            conference proceedings, book chapter, etc.) with this record.'),
+      'default_widget' => 'chado_linker__pub_widget',
+      'default_formatter' => 'chado_linker__pub_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
       ),
-    ),
-  );
-  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__pub_widget_info() {
-  return array(
-    'label' => t('Publications'),
-    'field types' => array('chado_linker__pub'),
-  );
-}
-/**
- * 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__pub_formatter_info() {
-  return array(
-    'label' => t('Publications'),
-    'field types' => array('chado_linker__pub'),
-    '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__pub_formatter(&$element, $entity_type, $entity, $field,
-    $instance, $langcode, $items, $display) {
-
-  $list_items = array();
-  $chado_table = $field['settings']['chado_table'];
-  foreach ($items as $delta => $item) {
-    if ($item[$chado_table . '__pub_id']) {
-      $pub = chado_generate_var('pub', array('pub_id' => $item[$chado_table . '__pub_id']));
-      $list_items[$pub->pyear] = $pub->uniquename;
-    }
+    );
   }
+  /**
+   * @see TripalField::attach_info()
+   */
+  function attach_info($entity_type, $bundle, $target) {
+    $field_info = array();
+
+    $table_name = $target['data_table'];
+    $type_table = $target['type_table'];
+    $type_field = $target['field'];
+    $cv_id      = $target['cv_id'];
+    $cvterm_id  = $target['cvterm_id'];
+
+    // If the linker table does not exists then we don't want to add attach.
+    $pub_table = $table_name . '_pub';
+    if (!chado_table_exists($pub_table)) {
+      return $field_info;
+    }
 
-  krsort($list_items, SORT_NUMERIC);
-
-  $list = array(
-    'title' => '',
-    'items' => $list_items,
-    'type' => 'ol',
-    'attributes' => array(),
-  );
-  $element[0] = array(
-    '#type' => 'markup',
-    '#markup' => theme_item_list($list),
-  );
-}
-/**
- *
- * @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__pub_widget(&$widget, $form, $form_state, $field,
-    $instance, $langcode, $items, $delta, $element) {
-
-  $entity = $form['#entity'];
-  $field_name = $field['field_name'];
-
-  // Get the FK column that links to the base table.
-  $table_name = $field['settings']['chado_table'];
-  $base_table = $field['settings']['base_table'];
-  $schema = chado_get_schema($table_name);
-  $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;
-  $pub_id = '';
-  $title = '';
-
-  // 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];
-    $pub_id = $items[$delta][$table_name . '__pub_id'];
-    $title = $items[$delta][$table_name . '--pub__uniquename'];
+    $schema = chado_get_schema($pub_table);
+    $pkey = $schema['primary key'][0];
+
+    // Initialize the field array.
+    $field_info = array(
+      'field_name' => $table_name . '__pub',
+      'field_type' => 'chado_linker__pub',
+      'widget_type' => 'chado_linker__pub_widget',
+      'widget_settings' => array('display_label' => 1),
+      'description' => '',
+      'label' => 'Publications',
+      'is_required' => 0,
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'storage' => 'field_chado_storage',
+      'field_settings' => array(
+        'chado_table' => $pub_table,
+        'chado_column' => $pkey,
+        'base_table' => $table_name,
+        'semantic_web' => array(
+          'name' => 'publication',
+          'accession' => 'publication',
+          'ns' => 'schema',
+          'nsurl' => 'https://schema.org/',
+        ),
+      ),
+    );
+    return $field_info;
+  }
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('Publications'),
+      'field types' => array('chado_linker__pub'),
+    );
+  }
+  /**
+   * @see TripalField::formatter_info()
+   */
+  function formatter_info() {
+    return array(
+      'label' => t('Publications'),
+      'field types' => array('chado_linker__pub'),
+      'settings' => array(
+      ),
+    );
   }
+  /**
+   * @see TripalField::formatter_view()
+   */
+  function formatter_view(&$element, $entity_type, $entity, $field,
+      $instance, $langcode, $items, $display) {
+
+    $list_items = array();
+    $chado_table = $field['settings']['chado_table'];
+    foreach ($items as $delta => $item) {
+      if ($item[$chado_table . '__pub_id']) {
+        $pub = chado_generate_var('pub', array('pub_id' => $item[$chado_table . '__pub_id']));
+        $list_items[$pub->pyear] = $pub->uniquename;
+      }
+    }
 
-  // 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);
-    $pub_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__pub_id');
-    $title = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__title');
+    krsort($list_items, SORT_NUMERIC);
+
+    $list = array(
+      'title' => '',
+      'items' => $list_items,
+      'type' => 'ol',
+      'attributes' => array(),
+    );
+    $element[0] = array(
+      '#type' => 'markup',
+      '#markup' => theme_item_list($list),
+    );
   }
+  /**
+   * @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'];
+
+    // Get the FK column that links to the base table.
+    $table_name = $field['settings']['chado_table'];
+    $base_table = $field['settings']['base_table'];
+    $schema = chado_get_schema($table_name);
+    $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;
+    $pub_id = '';
+    $title = '';
+
+    // 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][$table_name . '__' . $pkey];
+      $fkey_value = $items[$delta][$table_name . '__' . $fkey];
+      $pub_id = $items[$delta][$table_name . '__pub_id'];
+      $title = $items[$delta][$table_name . '--pub__uniquename'];
+    }
 
-  $schema = chado_get_schema('pub');
-
-  $widget['#table_name'] = $table_name;
-  $widget['#fkey_field'] = $fkey;
-  $widget['#element_validate'] = array('chado_linker__pub_widget_validate');
-  $widget['#theme'] = 'chado_linker__pub_widget';
-  $widget['#prefix'] =  "<span id='$table_name-$delta'>";
-  $widget['#suffix'] =  "</span>";
-
-  $widget['value'] = array(
-    '#type' => 'value',
-    '#default_value' => $record_id,
-  );
-  $widget[$table_name . '__' . $fkey] = array(
-    '#type' => 'value',
-    '#default_value' => $fkey_value,
-  );
-  $widget[$table_name . '__pub_id'] = array(
-    '#type' => 'value',
-    '#default_value' => $pub_id,
-  );
-
-  $widget[$table_name . '--pub__uniquename'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Publication ID'),
-    '#default_value' => $title,
-    '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/pub',
-    '#ajax' => array(
-      'callback' => "chado_linker__pub_widget_form_ajax_callback",
-      'wrapper' => "$table_name-$delta",
-      'effect' => 'fade',
-      'method' => 'replace'
-    ),
-    '#maxlength' => 100000,
-  );
-}
-/**
- * An Ajax callback for the pub widget.
- */
-function chado_linker__pub_widget_form_ajax_callback($form, $form_state) {
+    // 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 . '__' . $pkey);
+      $fkey_value = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__' . $fkey);
+      $pub_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__pub_id');
+      $title = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__title');
+    }
 
-  $field_name = $form_state['triggering_element']['#parents'][0];
-  $delta = $form_state['triggering_element']['#parents'][2];
+    $schema = chado_get_schema('pub');
+
+    $widget['#table_name'] = $table_name;
+    $widget['#fkey_field'] = $fkey;
+    $widget['#element_validate'] = array('chado_linker__pub_widget_validate');
+    $widget['#theme'] = 'chado_linker__pub_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 . '__' . $fkey] = array(
+      '#type' => 'value',
+      '#default_value' => $fkey_value,
+    );
+    $widget[$table_name . '__pub_id'] = array(
+      '#type' => 'value',
+      '#default_value' => $pub_id,
+    );
+
+    $widget[$table_name . '--pub__uniquename'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Publication ID'),
+      '#default_value' => $title,
+      '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/pub',
+      '#ajax' => array(
+        'callback' => "chado_linker__pub_widget_form_ajax_callback",
+        'wrapper' => "$table_name-$delta",
+        'effect' => 'fade',
+        'method' => 'replace'
+      ),
+      '#maxlength' => 100000,
+    );
+  }
 
-  return $form[$field_name]['und'][$delta];
+  /**
+   * @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'];
+
+    // 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' => array(),
+      $field_table . '__' . $pkey => '',
+      $field_table . '__' . $fkey_lcolumn => '',
+      $field_table . '__' . 'pub_id' => '',
+      $field_table . '--' . 'pub__uniquename' => '',
+    );
+
+    $linker_table = $base_table . '_pub';
+    $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) {
+        $pub = $linker->pub_id;
+        $pub_details = tripal_get_minimal_pub_info($pub);
+        $pub_details['@type'] = $pub->type_id->dbxref_id->db_id->name . ':' . $pub->type_id->dbxref_id->accession;
+        $pub_details['publication']['type'] = $pub->type_id->name;
+
+        $entity->{$field_name}['und'][$i]['value'] = $pub_details;
+        $entity->{$field_name}['und'][$i][$field_table . '__' . $pkey] = $linker->$pkey;
+        $entity->{$field_name}['und'][$i][$field_table . '__' . $fkey_lcolumn] = $linker->$fkey_lcolumn->$fkey_lcolumn;
+        $entity->{$field_name}['und'][$i][$field_table . '__' . 'pub_id'] = $pub->pub_id;
+        $entity->{$field_name}['und'][$i][$field_table . '--' . 'pub__uniquename'] =  $pub->uniquename;
+
+        if (property_exists($pub, 'entity_id')) {
+          $entity->{$field_name}['und'][$i]['entity_id'] = $pub->entity_id;
+          $entity->{$field_name}['und'][$i]['entity_type'] = 'TripalEntity';
+        }
+        $i++;
+      }
+    }
+  }
 }
 
 /**
@@ -280,6 +296,16 @@ function chado_linker__pub_widget_validate($element, &$form_state) {
   }
 
 }
+/**
+ * An Ajax callback for the pub widget.
+ */
+function chado_linker__pub_widget_form_ajax_callback($form, $form_state) {
+
+  $field_name = $form_state['triggering_element']['#parents'][0];
+  $delta = $form_state['triggering_element']['#parents'][2];
+
+  return $form[$field_name]['und'][$delta];
+}
 /**
  * Theme function for the pub widget.
  *
@@ -294,68 +320,12 @@ function theme_chado_linker__pub_widget($variables) {
   $fkey = $element['#fkey_field'];
 
   $layout = "
-    <div class=\"pub-widget\">
-      <div class=\"pub-widget-item\">" .
+      <div class=\"pub-widget\">
+        <div class=\"pub-widget-item\">" .
         drupal_render($element[$table_name . '--pub__uniquename']) . "
+        </div>
       </div>
-    </div>
-  ";
+    ";
 
   return $layout;
-}
-
-/**
- * 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__pub_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'];
-
-  // 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 . '__' . 'pub_id' => '',
-    $field_table . '--' . 'pub__uniquename' => '',
-  );
-
-  $linker_table = $base_table . '_pub';
-  $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) {
-      $pub = $linker->pub_id;
-      $entity->{$field_name}['und'][$i] = array(
-        'value' => $linker->$pkey,
-        $field_table . '__' . $fkey_lcolumn => $linker->$fkey_lcolumn->$fkey_lcolumn,
-        $field_table . '__' . 'pub_id' => $pub->pub_id,
-        $field_table . '--' . 'pub__uniquename' => $pub->uniquename,
-      );
-      $i++;
-    }
-  }
-}
-
+}

+ 25 - 12
tripal_chado/includes/fields/chado_linker__relationship.inc

@@ -101,11 +101,6 @@ class chado_linker__relationship extends TripalField {
     $headers = array('Subject' ,'Type', 'Object');
     $headers = array('Relationship');
 
-    $this_name = $entity->chado_record->name;
-    if (property_exists($entity->chado_record, 'uniquename')) {
-      $this_name = $entity->chado_record->uniquename;
-    }
-
     foreach ($items as $delta => $item) {
       if (!$item['value']) {
         continue;
@@ -187,6 +182,15 @@ class chado_linker__relationship extends TripalField {
     $field_column = $field['settings']['chado_column'];
     $base_table = $field['settings']['base_table'];
 
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = array(
+      'value' => array(),
+    );
+
+    if (!$record) {
+      return;
+    }
+
     // Expand the object to include the relationships.
     $options = array(
       'return_array' => 1,
@@ -222,8 +226,7 @@ class chado_linker__relationship extends TripalField {
       foreach ($orelationships as $relationship) {
         $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession;
         $rel_type = $relationship->type_id->name;
-        $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
-        $verb = $this->get_rel_verb($rel_type_clean);
+        $verb = $this->get_rel_verb($rel_type);
         $subject_name = $relationship->subject_id->name;
         $subject_type = $relationship->subject_id->type_id->name;
         $object_name = $relationship->object_id->name;
@@ -260,6 +263,7 @@ class chado_linker__relationship extends TripalField {
           $entity->{$field_name}['und'][$i]['value']['subject']['entity_id'] = $entity_id;
           $entity->{$field_name}['und'][$i]['value']['subject']['entity_type'] = 'TripalEntity';
         }
+        $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
         $entity->{$field_name}['und'][$i]['value']['phrase'] = 'The ' . $subject_type . ', ' .
           $subject_name . ', ' . $verb . ' '  . $rel_type_clean . ' this '  .
           $object_type . '.';
@@ -272,8 +276,7 @@ class chado_linker__relationship extends TripalField {
       foreach ($srelationships as $relationship) {
         $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession;
         $rel_type = $relationship->type_id->name;
-        $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
-        $verb = $this->get_rel_verb($rel_type_clean);
+        $verb = $this->get_rel_verb($rel_type);
         $subject_name = $relationship->subject_id->name;
         $subject_type = $relationship->subject_id->type_id->name;
         $object_name = $relationship->object_id->name;
@@ -309,6 +312,7 @@ class chado_linker__relationship extends TripalField {
           $entity->{$field_name}['und'][$i]['value']['object']['entity_id'] = $entity_id;
           $entity->{$field_name}['und'][$i]['value']['object']['entity_type'] = 'TripalEntity';
         }
+        $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
         $entity->{$field_name}['und'][$i]['value']['phrase'] = 'This  ' .
           $subject_type . ' ' . $verb . ' '  . $rel_type_clean . ' the '  .
           $object_type . ', ' . $object_name . '.';
@@ -316,9 +320,19 @@ class chado_linker__relationship extends TripalField {
       }
     }
   }
+  /**
+   * A helper function to define English verbs for relationship types.
+   *
+   * @param $rel_type
+   *   The vocabulary term name for the relationship.
+   *
+   * @return
+   *   The verb to use when creating a sentence of the relationship.
+   */
   private function get_rel_verb($rel_type) {
-    $verb = '';
-    switch ($rel_type) {
+    $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
+    $verb = $rel_type_clean;
+    switch ($rel_type_clean) {
       case 'integral part of':
       case 'instance of':
         $verb = 'is an';
@@ -345,7 +359,6 @@ class chado_linker__relationship extends TripalField {
       case 'maximally overlaps':
       case 'overlaps':
       case 'starts':
-        $verb = '';
         break;
       default:
         $verb = 'is';

+ 20 - 6
tripal_chado/includes/fields/chado_linker__synonym.inc

@@ -136,7 +136,7 @@ class chado_linker__synonym 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)) {
-      $record_id = $items[$delta]['value'];
+      $record_id = $items[$delta][$table_name . '__' . $pkey];
       $fkey_value = $items[$delta][$table_name . '__' . $fkey];
       $synonym_id = $items[$delta][$table_name . '__synonym_id'];
       $pub_id = $items[$delta][$table_name . '__pub_id'];
@@ -148,7 +148,7 @@ class chado_linker__synonym extends TripalField {
 
     // 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);
+      $record_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__' . $pkey);
       $fkey_value = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__' . $fkey);
       $synonym_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__synonym_id');
       $pub_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__pub_id');
@@ -173,7 +173,12 @@ class chado_linker__synonym extends TripalField {
     $widget['#prefix'] =  "<span id='$table_name-$delta'>";
     $widget['#suffix'] =  "</span>";
 
-    $widget['value'] = array(
+    $form['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['value'],
+    );
+
+    $widget[$table_name . '__' . $pkey] = array(
       '#type' => 'value',
       '#default_value' => $record_id,
     );
@@ -224,15 +229,19 @@ class chado_linker__synonym extends TripalField {
     $field_table = $field['settings']['chado_table'];
     $field_column = $field['settings']['chado_column'];
 
-    // Get the FK that links to the base record.
+    // Get the PKey for this table
     $schema = chado_get_schema($field_table);
     $pkey = $schema['primary key'][0];
+
+    // Get the FK that links to the base record.
+    $schema = chado_get_schema($field_table);
     $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' => '',
+      'value' => array(),
+      $field_table . '__' . $pkey => '',
       $field_table . '__' . $fkey_lcolumn => '',
       $field_table . '__' . 'synonym_id' => '',
       $field_table . '__' . 'pub_id' => '',
@@ -251,7 +260,12 @@ class chado_linker__synonym extends TripalField {
       foreach ($record->$linker_table as $index => $linker) {
         $synonym = $linker->synonym_id;
         $entity->{$field_name}['und'][$i] = array(
-          'value' => $linker->$pkey,
+          'value' => array(
+            '@type' => $synonym->type_id->dbxref_id->db_id->name . ':' . $synonym->type_id->dbxref_id->accession,
+            'type' => $synonym->type_id->name,
+            'name' => $synonym->name,
+          ),
+          $field_table . '__' . $pkey = $linker->$pkey,
           $field_table . '__' . $fkey_lcolumn => $linker->$fkey_lcolumn->$fkey_lcolumn,
           $field_table . '__' . 'synonym_id' => $synonym->synonym_id,
           $field_table . '__' . 'pub_id' => $linker->pub_id->pub_id,

+ 158 - 0
tripal_chado/includes/fields/chado_organism__type_id.inc

@@ -1 +1,159 @@
 <?php
+
+class chado_organism__type_id extends TripalField {
+
+  /**
+   * @see TripalField::info()
+   */
+  public function field_info() {
+    return array(
+      'label' => t('Infraspecific Type'),
+      'description' => t('A field for specifying an infraspecific type.'),
+      'default_widget' => 'chado_organism__type_id_widget',
+      'default_formatter' => 'chado_organism__type_id_formatter',
+      'settings' => array(
+      ),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    );
+  }
+  /**
+   * @see TripalField::attach_info()
+   */
+  public function attach_info($entity_type, $bundle, $settings) {
+
+    $field_info = array();
+
+    $table_name = $settings['data_table'];
+    $type_table = $settings['type_table'];
+    $type_field = $settings['field'];
+    $cv_id      = $settings['cv_id'];
+    $cvterm_id  = $settings['cvterm_id'];
+
+    $schema = chado_get_schema($table_name);
+
+    // If this is the organism table and Chado v1.3 then attach.
+    if ($table_name == 'organism' and array_key_exists('type_id', $schema['fields'])) {
+      $field_info = array(
+        'field_name' => 'organism__type_id',
+        'field_type' => 'chado_organism__type_id',
+        'widget_type' => 'chado_organism__type_id_widget',
+        'description' => 'Select an Infraspecific Type.',
+        'label' => 'Infrapsecific Type',
+        'is_required' => 0,
+        'storage' => 'field_chado_storage',
+        'widget_settings' => array(
+          'display_label' => 1
+        ),
+        'field_settings' => array(
+          'chado_table' => 'organism',
+          'chado_column' => 'type_id',
+          'semantic_web' => array(
+            'name' => 'infraspecificTaxon',
+            'accession' => '0000046',
+            'ns' => 'TAXRANK',
+            'nsurl' => 'https://github.com/phenoscape/taxrank',
+          ),
+        ),
+      );
+    }
+    return $field_info;
+  }
+
+  /**
+   * @see TripalField::widget_info()
+   */
+  public function widget_info() {
+    return array(
+      'label' => t('Infraspecific Type'),
+      'field types' => array('chado_organism__type_id')
+    );
+  }
+  /**
+   * @see TripalField::formatter_info()
+   */
+  public function formatter_info() {
+    return array(
+      'label' => t('Infraspecific Type'),
+      'field types' => array('chado_organism__type_id'),
+      'settings' => array(
+      ),
+    );
+  }
+
+  /**
+   * @see TripalField::widget()
+   */
+  public 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'];
+
+    $default_value = 0;
+    if (array_key_exists('organism__type_id', $items[0])) {
+      $default_value = $items[0]['organism__type_id'];
+    }
+
+    $form['value'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['value'],
+    );
+
+    $cv = tripal_get_default_cv($field_table, $field_column);
+    $options = tripal_get_cvterm_select_options($cv->cv_id);
+    $widget['organism__type_id'] = array(
+      '#type' => 'select',
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#options' => $options,
+      '#default_value' => $default_value,
+      '#required' => $element['#required'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#delta' => $delta,
+      '#element_validate' => array('chado_organism__type_id_widget_validate'),
+    );
+  }
+
+  /**
+   * @see TripalField::load()
+   */
+  public 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'];
+
+    $organism = $record->organism_id;
+
+    $entity->{$field_name}['und'][0]['value'] = $organism->type_id->name;
+    $entity->{$field_name}['und'][0]['organism__type_id'] = $organism->type_id->cvterm_id;
+  }
+
+}
+
+
+/**
+ * Callback function for validating the chado_organism__type_id_widget.
+ */
+function chado_organism__type_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'];
+
+
+}

+ 38 - 16
tripal_chado/includes/tripal_chado.field_storage.inc

@@ -36,6 +36,7 @@ function tripal_chado_field_storage_write($entity_type, $entity, $op, $fields) {
 
   // Convert the fields into a key/value list of fields and their values.
   $field_vals = tripal_chado_field_storage_unnest_fields($fields, $entity_type, $entity);
+dpm($field_vals);
 
   // Recursively write fields for the base table.
   $record_id = tripal_chado_field_storage_write_recursive($entity_type, $entity, $term,
@@ -58,6 +59,7 @@ function tripal_chado_field_storage_write($entity_type, $entity, $op, $fields) {
     }
   }
 
+
   // Now that we have handled the base table, we need to handle fields that
   // are not part of the base table.
   foreach ($fields as $field_id) {
@@ -73,9 +75,11 @@ function tripal_chado_field_storage_write($entity_type, $entity, $op, $fields) {
         $field_table = $field['settings']['chado_table'];
 
         // Iterate through each record.
-        foreach ($field_vals[$field_name] as $delta => $fvals) {
-          tripal_chado_field_storage_write_recursive($entity_type, $entity, $term,
-              $op, $fvals, $base_table, $field_table);
+        if (array_key_exists($field_name, $field_vals)) {
+          foreach ($field_vals[$field_name] as $delta => $fvals) {
+            tripal_chado_field_storage_write_recursive($entity_type, $entity, $term,
+                $op, $fvals, $base_table, $field_table);
+          }
         }
       }
     }
@@ -134,9 +138,8 @@ 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]['value'];
+        $fk_val = $field_vals[$fk_field_name][0][$base_table . '__' . $local_id];
         $fk_vals = $field_vals[$fk_field_name][0];
-        unset($fk_vals['value']);
       }
 
       // Don't recurse if the value of the FK field is set to NULL.  The
@@ -186,12 +189,12 @@ function tripal_chado_field_storage_write_recursive($entity_type, $entity, $term
       }
 
       // If the value is empty then exclude this field
-      if (!$items[0]['value']) {
+      if (!$items[0][$tablename . '__' . $chado_field]) {
         continue;
       }
 
       // Add the value of the field to the $values arr for later insert/update.
-      $values[$chado_field] = $items[0]['value'];
+      $values[$chado_field] = $items[0][$tablename . '__' . $chado_field];
     }
   }
 
@@ -222,6 +225,8 @@ function tripal_chado_field_storage_write_recursive($entity_type, $entity, $term
   }
   // We have an incoming record_id so this is an update.
   else {
+    // TODO: what if the unique constraint matches another record?  That is
+    // not being tested for here.
     $match[$pkey_field] = $record_id;
     if (!chado_update_record($tablename, $match, $values)) {
       drupal_set_message("Could not update Chado record in table: $tablename.", 'error');
@@ -317,10 +322,13 @@ function tripal_chado_field_storage_load($entity_type, $entities, $age,
           // and because $record object is created by the chado_generate_var()
           // function we must go one more level deeper to get the value
           if (is_object($record->$field_column)) {
-            $entity->{$field_name}['und'][0]['value'] = $record->$field_column->$field_column;
+            $entity->{$field_name}['und'][0][$field_table . '__' . $field_column] = $record->$field_column->$field_column;
           }
           else {
+            // For non FK fields we'll make the field value be the same
+            // as the column value.
             $entity->{$field_name}['und'][0]['value'] = $record->$field_column;
+            $entity->{$field_name}['und'][0][$field_table . '__' . $field_column] = $record->$field_column;
           }
         }
 
@@ -373,25 +381,40 @@ function tripal_chado_field_storage_unnest_fields($fields, $entity_type, $entity
   // Iterate through all of the fields.
   foreach ($fields as $field_id => $ids) {
 
-    // Get the field name and all of it's items.
+    // Get the field name and information about it.
     $field = field_info_field_by_id($field_id);
     $field_name = $field['field_name'];
-    $items = field_get_items($entity_type, $entity, $field_name);
+    // Some fields (e.g. chado_linker_cvterm_adder) don't add data to
+    // Chado so they don't have a table, but they are still attached to the
+    // entity. Just skip these.
+    if (!array_key_exists('chado_table', $field['settings'])) {
+      continue;
+    }
+    $chado_table = $field['settings']['chado_table'];
+    $chado_column = $field['settings']['chado_column'];
 
     // 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) {
-        if ($item_name == 'value') {
-          $new_fields[$field_name][$delta]['value'] = $value;
-          continue;
-        }
         $matches = array();
         if (preg_match('/^(.*?)__.*?$/', $item_name, $matches)) {
           $table_name = $matches[1];
-          $new_fields[$field_name][$delta][$item_name][0]['value'] = $value;
+          $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.
+      $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])) {
+        $new_fields[$field_name][$delta][$item_name] = $items[$delta]['value'];
+      }
     }
   }
   return $new_fields;
@@ -407,7 +430,6 @@ function tripal_chado_field_storage_unnest_fields($fields, $entity_type, $entity
  * appear to actually need to do anything...
  */
 function tripal_chado_field_storage_query($query) {
-  dpm($query);
   $fieldConditions = $query->fieldConditions;
   foreach ($fieldConditions as $condition) {
     $field = $condition['field'];

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

@@ -251,7 +251,23 @@ function tripal_chado_get_field_form_values($field_name, $form_state, $delta = 0
 }
 
 /**
- * Sets the values of the field from the $form_state.
+ * Sets the values of the field from the $form_state.  If no child
+ * argument is specified then the 'value' field is set.
+ *
+ * @param $field_name
+ *   The name of the field to set.
+ * @param $form_state
+ *   The form's form_state array.
+ * @param $newvalue
+ *   The new value to set for the field.
+ * @param $delta
+ *   If cardinality of a field is greater than 1 the delta indicates
+ *   which instance to set.
+ * @param $child
+ *   The name of the property to set iff other than 'value'.
+ *
+ * @return
+ *   TRUE if the value was set, FALSE otherwise.
  */
 function tripal_chado_set_field_form_values($field_name, &$form_state, $newvalue, $delta = 0, $child = NULL) {
   // The form_state must have the 'values' key. If not then just return.

+ 3 - 3
tripal_ws/includes/tripal_ws.rest.inc

@@ -436,7 +436,7 @@ function tripal_ws_get_content($api_url, &$response, $ws_args, $ctype, $entity_i
 
   if (!array_key_exists($vocab->namespace, $response['@context'])) {
     // If there is no URL prefix then use this API's vocabulary API
-    if ($term->urlprefix) {
+    if (property_exists($term, 'urlprefix')) {
       $response['@context'][$vocab->namespace] = $term->urlprefix;
     }
     else {
@@ -510,7 +510,6 @@ function tripal_ws_get_content($api_url, &$response, $ws_args, $ctype, $entity_i
         $lentity = reset($lentity);
         $lterm = tripal_load_term_entity(array('term_id' => $lentity->term_id));
         $lvocab = tripal_load_vocab_entity(array('vocab_id' => $lterm->vocab_id));
-        $lterm_details = tripal_get_term_details($lvocab->namespace, $lterm->namespace);
         $value[] = array(
           '@id'   => $api_url . '/content/' . $lterm->name . '/' . $items[0]['entity_id'],
           '@type' => $lvocab->namespace . ':' . $lterm->accession,
@@ -518,7 +517,8 @@ function tripal_ws_get_content($api_url, &$response, $ws_args, $ctype, $entity_i
           'type' => $lterm->name,
         );
 
-        if (!array_key_exists($lvocab->namespace, $response['@context'])) {
+        if (property_exists($lvocab, 'namespace') and !array_key_exists($lvocab->namespace, $response['@context'])) {
+          $lterm_details = tripal_get_term_details($lvocab->namespace, $lterm->namespace);
           $response['@context'][$lvocab->namespace] = $lterm_details->url;
         }
       }