Browse Source

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

Stephen Ficklin 10 năm trước cách đây
mục cha
commit
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;
         }
       }