Explorar el Código

kvproperty tables now seem to be working

Stephen Ficklin hace 9 años
padre
commit
a19ed81c95

+ 45 - 0
tripal_entities/includes/TripalEntity.inc

@@ -5,6 +5,51 @@
 class TripalEntity extends Entity {
   public function __construct($values = array(), $entity_type) {
     parent::__construct($values, $entity_type);
+
+    // If we have an ID then this entity has been saved and it will
+    // also therefore have a chado_entity record.  We want to
+    // load this record so it is always part of the entity object.
+    if (property_exists($this, 'id') and $this->id) {
+      // For Tripal created entities add in the chado_entity details.
+      $dbs = tripal_entities_get_db_names_for_published_vocabularies();
+      if (in_array($this->type, $dbs)) {
+        $details = db_select('chado_entity', 'ce')
+          ->fields('ce')
+          ->condition('entity_id', $this->id)
+          ->execute()
+          ->fetchObject();
+
+        // Add the chado entity details to the entity in case it's needed
+        // downstream (e.g. in field widget construction).
+        $this->chado_entity_id = $details->chado_entity_id;
+        $this->chado_table = $details->data_table;
+        $this->chado_field = $details->field;
+
+        // Add in the record.
+        $schema = chado_get_schema($this->chado_table);
+        $pkey = $schema['primary key'][0];
+        $this->chado_record_id = $details->record_id;
+        $this->chado_record = chado_generate_var($this->chado_table, array($pkey =>+ $details->record_id));
+      }
+    }
+    // If we do not have an ID then we need to do a few queries to get
+    // information about the chado table this entity maps to.
+    else {
+      // Use the cvterm_id to look up the base table for this term.  We find
+      // the base table by looking in the term_usage table for the mapping.
+      $sel_values = array(
+        'term_id' => array(
+          'cvterm_id' => $this->cvterm_id,
+        ),
+      );
+      $term_usage = chado_generate_var('tripal_term_usage', $sel_values, array('return_array' => 1));
+
+      // For each table that uses this term, insert the field recursively
+      foreach ($term_usage as $usage) {
+        $this->chado_table = $usage->data_table;
+        $this->chado_field = $usage->field;
+      }
+    }
   }
 
   protected function defaultLabel() {

+ 32 - 9
tripal_entities/includes/TripalEntityController.inc

@@ -12,7 +12,9 @@ class TripalEntityController extends EntityAPIController {
   }
 
   /**
-   * Create a Tripal data entity - we first set up the values that are specific
+   * Create a Tripal data entity
+   *
+   * We first set up the values that are specific
    * to our data schema but then also go through the EntityAPIController
    * function.
    *
@@ -23,14 +25,35 @@ class TripalEntityController extends EntityAPIController {
    *   An object with all default fields initialized.
    */
   public function create(array $values = array()) {
-    // Add values that are specific to our entity
-    $values += array(
-      'id' => '',
-      'bundle' => '',
-      'title' => '',
-      'created' => '',
-      'changed' => '',
-    );
+    // Add some items to the values array passed to the constructor
+    global $user;
+    $values['uid'] = $user->uid;
+    $values['created'] = time();
+    $values['changed'] = time();
+    $values['title'] = '';
+
+    // The incoming values should have at a minimum the bundle_id;
+    $bundle = $values['bundle'];
+    $matches = array();
+    if (preg_match('/(.*)_(.*)/', $bundle, $matches)) {
+      $type = $matches[1];
+      $accession = $matches[2];
+      $values['type'] = $type;
+
+      // Get the CVterm.
+      $match = array(
+        'dbxref_id' => array(
+          'accession' => $accession,
+          'db_id' => array(
+            'name' => $type,
+          ),
+        ),
+      );
+      $cvterm = chado_generate_var('cvterm', $match);
+      if ($cvterm) {
+        $values['cvterm_id'] = $cvterm->cvterm_id;
+      }
+    }
 
     return parent::create($values);
   }

+ 1 - 16
tripal_entities/includes/tripal_entities.chado_entity.inc

@@ -23,22 +23,7 @@ function tripal_entities_entity_postsave($entity, $type) {
  * Implements hook_entity_load().
  */
 function tripal_entities_entity_load($entities, $type) {
-  foreach ($entities as $entity) {
-
-    // For Tripal created entities add in the chado_entity details.
-    $dbs = tripal_entities_get_db_names_for_published_vocabularies();
-    if (in_array($entity->type, $dbs)) {
-      $details = db_select('chado_entity', 'ce')
-        ->fields('ce')
-        ->condition('entity_id', $entity->id)
-        ->execute()
-        ->fetchObject();
-
-      // Add teh chado entity details to the entity in case it's needed
-      // downstream (e.g. in field widget construction).
-      $entity->chado_entity = $details;
-    }
-  }
+
 }
 
 /**

+ 2 - 1
tripal_entities/includes/tripal_entities.entity_form.inc

@@ -176,7 +176,8 @@ function tripal_entities_entity_form_add_new($bundle_id, $cvterm, &$form, &$form
 
   // If the entity doesn't exist then create one.
   if (!$entity) {
-    $entity = entity_get_controller($cvterm->dbxref_id->db_id->name)->create(array('bundle' => $bundle_id));
+    $entity_type = $cvterm->dbxref_id->db_id->name;
+    $entity = entity_get_controller($entity_type)->create(array('bundle' => $bundle_id));
     field_attach_form($cvterm->dbxref_id->db_id->name, $entity, $form, $form_state);
 
     $form['add_button'] = array(

+ 19 - 8
tripal_fields/includes/fields/dbxref_id.inc

@@ -42,15 +42,14 @@ function tripal_fields_dbxref_id_formatter(&$element, $entity_type, $entity, $fi
  * @param unknown $element
  */
 function tripal_fields_dbxref_id_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-
   $field_name = $field['field_name'];
 
   // Get the field defaults.
-  $dbxref_id = $items[0]['value'];
-  $db_id = $items[0]['dbxref__db_id'];
-  $accession = $items[0]['dbxref__accession'];
-  $version = $items[0]['dbxref__version'];
-  $description = $items[0]['dbxref__description'];
+  $dbxref_id = $items[$delta]['value'];
+  $db_id = $items[$delta]['dbxref__db_id'];
+  $accession = $items[$delta]['dbxref__accession'];
+  $version = $items[$delta]['dbxref__version'];
+  $description = $items[$delta]['dbxref__description'];
 
   // If we are here because our parent was triggered in a form submit
   // then that means an ajax call was made and we don't want the fieldset to
@@ -254,18 +253,30 @@ function theme_tripal_fields_dbxref_id_widget($variables) {
  * Loads the field values with appropriate data.
  *
  * This function is called by the tripal_fields_field_storage_load() for
- * each property managed by the field_chado_storage storage type.
+ * 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 tripal_fields_dbxref_id_field_load($field, $entity, $record) {
+function tripal_fields_dbxref_id_field_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'];
 
+  // Set some defauls for the empty record
+  $entity->{$field_name}['und'][0] = array(
+    'value' => '',
+    'dbxref__db_id' => '',
+    'dbxref__accession' => '',
+    'dbxref__version' => '',
+    'dbxref__description' => '',
+  );
 
   // Get the primary dbxref record.  Because we have a dbxref_id passed in
   // by the base record, we will only have one record.

+ 138 - 25
tripal_fields/includes/fields/kvproperty.inc

@@ -13,14 +13,18 @@
 function tripal_fields_kvproperty_formatter(&$element, $entity_type, $entity, $field,
   $instance, $langcode, $items, $display) {
 
-  $content = '';
+  $field_name = $field['field_name'];
+  $chado_tabe = $field['settings']['chado_table'];
+
+  $properties = array();
   foreach ($items as $delta => $item) {
-    $content =  key_exists('value', $item) ? $item['value'] : '';
-    $element[$delta] = array(
-      '#type' => 'markup',
-      '#markup' => $content,
-    );
+    $properties[] = $item[$chado_tabe . '__value'];
   }
+  $content = implode(', ', $properties);
+  $element[$delta] = array(
+    '#type' => 'markup',
+    '#markup' => $content,
+  );
 }
 /**
  *
@@ -36,8 +40,7 @@ function tripal_fields_kvproperty_formatter(&$element, $entity_type, $entity, $f
  * @param unknown $element
  */
 function tripal_fields_kvproperty_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-
-  $chado_entity = $form['#entity']->chado_entity;
+  $entity = $form['#entity'];
   $field_name = $field['field_name'];
 
   $matches = array();
@@ -50,16 +53,23 @@ function tripal_fields_kvproperty_widget(&$widget, $form, $form_state, $field, $
   $table_name = $matches[1];
   $cvterm_id = $matches[2];
 
-  // Get the name of the pkey field for this property table.
+  // Get the name of the pkey field for this property table and the name
+  // of the FK field that links to the base table.
   $schema = chado_get_schema($table_name);
   $pkey = $schema['primary key'][0];
+  $lfkey_field = key($schema['foreign keys'][$entity->chado_table]['columns']);
+  $rfkey_field = $schema['foreign keys'][$entity->chado_table]['columns'][$lfkey_field];
 
-  // Get the name of the FK field that links to the base data table.
-  $schema = chado_get_schema($chado_entity->data_table);
-  $fk = $schema['primary key'][0];
+  // Get the field defaults.
+  $fk_value = '';
+  $propval = '';
+  if (array_key_exists($delta, $items)) {
+    $propval = $items[$delta][$table_name . '__value'];
+  }
+  if (property_exists($entity, 'chado_record')) {
+    $fk_value = $entity->chado_record->$rfkey_field;
+  }
 
-  $pkey_value = '';
-  $fk_value = $chado_entity->record_id;
 
   // The group of elements all-together need some extra functionality
   // after building up the full list (like draggable table rows).
@@ -72,21 +82,17 @@ function tripal_fields_kvproperty_widget(&$widget, $form, $form_state, $field, $
   $widget['#element_validate'] = array('tripal_fields_kvproperty_widget_validate');
   $widget['#cardinality'] = 1;
 
-  $widget['value'][$delta] = array(
-    '#type' => 'hidden',
-    '#value' => $pkey_value,
-  );
-  $widget[$table_name . '__' . $pkey] = array(
+  $widget['value'] = array(
     '#type' => 'hidden',
-    '#value' => $pkey_value,
+    '#default_value' => !empty($items[$delta]['value']) ? $items[$delta]['value'] : '',
   );
-  $widget[$table_name . '__' . $fk] = array(
+  $widget[$table_name . '__' . $lfkey_field] = array(
     '#type' => 'hidden',
     '#value' => $fk_value,
   );
   $widget[$table_name . '__value'] = array(
     '#type' => 'textfield',
-    '#default_value' => !empty($items) ? $items[0] : '',
+    '#default_value' => $propval,
   );
   $widget[$table_name . '__type_id'] = array(
     '#type' => 'hidden',
@@ -96,7 +102,6 @@ function tripal_fields_kvproperty_widget(&$widget, $form, $form_state, $field, $
     '#type' => 'hidden',
     '#value' => $delta,
   );
-
   return $widget;
 }
 
@@ -113,10 +118,118 @@ function tripal_fields_kvproperty_widget_form_ajax_callback($form, $form_state)
  * Callback function for validating the tripal_fields_kvproperty_widget.
  */
 function tripal_fields_kvproperty_widget_validate($element, &$form_state) {
-   $field_name = $element['#field_name'];
+  $field_name = $element['#field_name'];
+  $delta = $element['#delta'];
+  $entity = $element['#entity'];
+  $matches = array();
+
+  // Get the table name and cvterm_id for this field.
+  preg_match('/(.*?)__(\d+)/', $field_name, $matches);
+  $table_name = $matches[1];
+  $cvterm_id = $matches[2];
+
+  // Get the name of the pkey field for this property table and the name
+  // of the FK field that links to the base table.
+  $schema = chado_get_schema($table_name);
+  $pkey = $schema['primary key'][0];
+  $lfkey_field = key($schema['foreign keys'][$entity->chado_table]['columns']);
+
+  // If we don't have a property value then we need to set all other fields
+  // to be empty so that when the module tries to save the field on the
+  // entity it won't try to save a partial record.
+  $pkey_val = tripal_fields_get_field_form_values($field_name, $form_state, $delta);
+  $prop_value = tripal_fields_get_field_form_values($field_name, $form_state, $delta, $table_name . "__value");
+  $fk_val = tripal_fields_get_field_form_values($field_name, $form_state, $delta, $table_name . '__' . $lfkey_field);
+  $type_id = tripal_fields_get_field_form_values($field_name, $form_state, $delta, $table_name . '__type_id');
+
+  if (!$prop_value) {
+    tripal_fields_set_field_form_values($field_name, $form_state, '', $delta);
+    tripal_fields_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__' . $lfkey_field);
+    tripal_fields_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__value');
+    tripal_fields_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__type_id');
+    tripal_fields_set_field_form_values($field_name, $form_state, '', $delta, $table_name . '__rank');
+  }
+  else {
+    $rank = tripal_fields_get_field_form_values($field_name, $form_state, $delta, '_weight');
+    tripal_fields_set_field_form_values($field_name, $form_state, $rank, $delta, $table_name . '__rank');
+  }
+  // Remove the properties for this record. We will re-add it. Otherwise,
+  // if we change ranks, we wind up with multiple records in the property table.
+  if ($pkey_val) {
+    $match = array(
+      $pkey => $pkey_val
+    );
+    chado_delete_record($table_name, $match);
+  }
 }
 /**
  * Callback function for submitting the tripal_fields_kvproperty_widget.
  */
 function tripal_fields_kvproperty_widget_submit($element, &$form_state) {
-}
+}
+
+/**
+ * Loads the field values with appropriate data.
+ *
+ * This function is called by the tripal_fields_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 tripal_fields_kvproperty_field_load($field, $entity, $base_table, $record) {
+
+  $field_name = $field['field_name'];
+  $field_type = $field['type'];
+  $field_table = $field['settings']['chado_table'];
+  $field_column = $field['settings']['chado_column'];
+
+  $matches = array();
+  preg_match('/(.*?)__(\d+)/', $field_name, $matches);
+  $table_name = $matches[1];
+  $cvterm_id = $matches[2];
+
+  // Get the FK that links to the base record.
+  $schema = chado_get_schema($field_table);
+  $pkey = $schema['primary key'][0];
+  $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
+  $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
+
+  // Set some defaults for the empty record.
+  $entity->{$field_name}['und'][0] = array(
+    'value' => '',
+    $field_table . '__' . $fkey_lcolumn => '',
+    $field_table . '__value' => '',
+    $field_table . '__type_id' => '',
+    $field_table . '__rank' => '',
+  );
+
+  // Get the properties associated with this base record for this fields
+  // given type.
+  $columns = array('*');
+  $match = array(
+    $fkey_lcolumn => $record->$fkey_rcolumn,
+    'type_id' => $cvterm_id,
+  );
+  $options = array(
+    'return_array' => TRUE,
+    'order_by' => array('rank' => 'ASC')
+  );
+  $properties = chado_select_record($field_table, $columns, $match, $options);
+  for ($i = 0; $i < count($properties); $i++) {
+    $property = $properties[$i];
+    foreach ($schema['fields'] as $fname => $details) {
+      $entity->{$field_name}['und'][$i] = array(
+        'value' => $property->$pkey,
+        $field_table . '__' . $fkey_lcolumn => $property->$fkey_lcolumn,
+        $field_table . '__value' => $property->value,
+        $field_table . '__type_id' => $property->type_id,
+        $field_table . '__rank' => $property->rank,
+      );
+    }
+  }
+}

+ 7 - 1
tripal_fields/includes/fields/kvproperty_adder.inc

@@ -106,12 +106,18 @@ function tripal_fields_kvproperty_adder_widget_validate($element, &$form_state)
      $term = chado_generate_var('cvterm', array('name' => $kvproperty), $options = array('return_array' => TRUE));
      if (count($term) == 1) {
        $prop_field_name = $field_name . '__' . $term[0]->cvterm_id;
+
+       // The field name is the table name in this case. We want to get the
+       // primary key as this should be the field that maps th the value.
+       $schema = chado_get_schema($field_name);
+       $pkey = $schema['primary key'][0];
+
        $field_info = array(
          'field_type' => 'kvproperty',
          'widget_type' => 'tripal_fields_kvproperty_widget',
          'field_settings' => array(
            'chado_table' => $field_name,
-           'chado_column' => 'type_id',
+           'chado_column' => $pkey,
          ),
          'widget_settings' => array(),
          'description' => $term[0]->definition ? $term[0]->definition : '',

+ 86 - 97
tripal_fields/includes/tripal_fields.field_storage.inc

@@ -25,83 +25,75 @@ function tripal_fields_field_storage_query($query) {
  */
 function tripal_fields_field_storage_write($entity_type, $entity, $op, $fields) {
 
+  // Get the base table, type field and record_id from the entity.
+  $base_table = $entity->chado_table;
+  $type_field = $entity->chado_field;
+  $record_id  = property_exists($entity, 'chado_record_id') ? $entity->chado_record_id : NULL;
+
   // Convert the fields into a key/value list of fields and their values.
   $field_vals = tripal_fields_field_storage_unnest_fields($fields, $entity_type, $entity);
 
-  $data_table = NULL;
-  $type_field = NULL;
-  $record_id = NULL;
-  switch ($op) {
-    case FIELD_STORAGE_INSERT:
-      // Use the cvterm_id to look up tables where this term is used
-      $sel_values = array(
-        'term_id' => array(
-          'cvterm_id' => $entity->cvterm_id,
-        ),
-      );
-      $term_usage = chado_generate_var('tripal_term_usage', $sel_values, array('return_array' => 1));
-
-      // For each table that uses this term, insert the field recursively
-      foreach ($term_usage as $usage) {
-        $data_table = $usage->data_table;
-        //$type_table = $usage->type_table;
-        $type_field = $usage->field;
-
-        // Recursively write fields for the base table.
-        tripal_fields_field_storage_write_recursive($entity_type, $entity,
-          $op, $field_vals, $data_table, $type_field);
-
-        // Now get the new chado_entity that was just added.
-        $details = db_select('chado_entity', 'ce')
-          ->fields('ce')
-          ->condition('entity_id', $entity->id)
-          ->execute()
-          ->fetchObject();
-        $data_table = $details->data_table;
-        $type_field = $details->field;
-        $record_id = $details->record_id;
+  // Recursively write fields for the base table.
+  $record_id = tripal_fields_field_storage_write_recursive($entity_type, $entity,
+      $op, $field_vals, $base_table, $base_table, $type_field, $record_id);
 
-      }
-      break;
-
-    case FIELD_STORAGE_UPDATE :
-
-      // Get the base table and record id for the fields of this entity.
-      $details = db_select('chado_entity', 'ce')
-        ->fields('ce')
-        ->condition('entity_id', $entity->id)
-        ->execute()
-        ->fetchObject();
-      $data_table = $details->data_table;
-      $type_field = $details->field;
-      $record_id = $details->record_id;
-
-      tripal_fields_field_storage_write_recursive($entity_type, $entity,
-        $op, $field_vals, $data_table, $type_field, $record_id);
-      if (!$details) {
-        // TODO: what to do if record is missing!
-      }
-      break;
+  // If this is an insert then add the chado_entity record.
+  if ($op == FIELD_STORAGE_INSERT) {
+    // Add a record to the chado_entity table so that the data for the
+    // fields can be pulled from Chado when loaded the next time.
+    $record = array(
+      'entity_id' => $entity->id,
+      'record_id' => $record_id,
+      'data_table' => $tablename,
+      'type_table' => $tablename, // TODO: this must be fixed.
+      'field' => $type_field,
+    );
+    $success = drupal_write_record('chado_entity', $record);
+    if (!$success) {
+      drupal_set_message('Unable to insert new Chado entity.', 'error');
+    }
   }
 
-  // Recursively write fields for any referring tables that have
-  // values in the $field_vals array.  There should be a key for each
-  // FK table in the $field_vals array.
-//   $schema = chado_get_schema($data_table);
-//   $rtables = $schema['referring_tables'];
-//   foreach ($rtables as $rtable) {
-//     if (array_key_exists($rtable, $field_vals)) {
-//       tripal_fields_field_storage_write_recursive($entity_type, $entity,
-//           $op, $field_vals, $rtable, NULL, NULL, 1);
-//     }
-//   }
+  // 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) {
+    // Get the field using the id.
+    $field = field_info_field_by_id($field_id);
+    $field_name = $field['field_name'];
+
+    // If the field has a chado_table setting then we can try to write.
+    if (array_key_exists('settings', $field) and array_key_exists('chado_table', $field['settings'])) {
+
+      // Skip fields that use the base table, as we've already handled those.
+      if ($field['settings']['chado_table'] != $base_table){
+        $field_table = $field['settings']['chado_table'];
+
+        // Iterate through each record.
+        foreach ($field_vals[$field_name] as $delta => $fvals) {
+          tripal_fields_field_storage_write_recursive($entity_type, $entity,
+              $op, $fvals, $base_table, $field_table);
+        }
+      }
+    }
+  }
 }
 
 /**
- * Implements hook_field_storage_write_recursive().
+ *
+ * @param $entity_type
+ * @param $entity
+ * @param $op
+ * @param $field_vals
+ * @param $tablename
+ * @param $type_field
+ * @param $record_id
+ * @param $depth
+ * @throws Exception
+ * @return
+ *   The record_id of the table if a matching record exists.
  */
 function tripal_fields_field_storage_write_recursive($entity_type, $entity,
-   $op, $field_vals, $tablename, $type_field = NULL,
+   $op, $field_vals, $base_table, $tablename, $type_field = NULL,
    $record_id = NULL, $depth = 0) {
 
   // Intialize the values array.
@@ -113,22 +105,25 @@ function tripal_fields_field_storage_write_recursive($entity_type, $entity,
   $pkey_field = $schema['primary key'][0];
   $fkey_fields = $schema['foreign keys'];
   $fkey_fields_list = array();
+  $fkey_base_linker = NULL;
 
   // STEP 1: Recurse on the FK fields.
   // Loop through the foreign keys so that we can recurse on those first.
   foreach ($fkey_fields as $fk_table => $details) {
     foreach ($details['columns'] as $local_id => $remote_id) {
-      // If this is the base table then do not recurse on the type_id.  The
-      // type_id is set in the entity.  We are at the base table when
-      // the depth is 0.
-      if ($depth == 0 && $local_id == $type_field) {
+
+      // If this is the base table then do not recurse on the type_id.
+      if ($tablename == $base_table && $local_id == $type_field) {
         $values[$local_id] = $entity->cvterm_id;
         continue;
       }
 
-      // Keep track of the FK fields so that in STEP 2 we don't have to
-      // loop through the $fk_fields again.
-      $fkey_fields_list[] = $local_id;
+      // If this is not the base table then do not recurse on the FK field
+      // that links this table to the base table.
+      if ($tablename != $base_table && $details['table'] == $base_table) {
+        $fkey_base_linker = $local_id;
+        continue;
+      }
 
       // Get the value of the FK field as provided by the user.
       $fk_val = NULL;
@@ -147,16 +142,19 @@ function tripal_fields_field_storage_write_recursive($entity_type, $entity,
         continue;
       }
 
-      // Don't recuse if there are no values to select/insert a foreign key.
+      // Don't recuse if there are no fkvals.
       if (count(array_keys($fk_vals)) == 0) {
-        $values[$local_id] = $fk_val;
         continue;
       }
 
+      // Keep track of the FK fields so that in STEP 2 we don't have to
+      // loop through the $fk_fields again.
+      $fkey_fields_list[] = $local_id;
+
       // Recurse on the FK field.  Pass in the ID for the FK field if one
       // exists in the $field_vals;
       $fk_val = tripal_fields_field_storage_write_recursive($entity_type,
-        $entity, $op, $fk_vals, $fk_table, NULL, $fk_val, $depth + 1);
+        $entity, $op, $fk_vals, $base_table, $fk_table, NULL, $fk_val, $depth + 1);
       if (isset($fk_val) and $fk_val != '' and $fk_val != 0) {
         $values[$local_id] = $fk_val;
       }
@@ -167,7 +165,6 @@ function tripal_fields_field_storage_write_recursive($entity_type, $entity,
   // Loop through the fields passed to the function and find any that
   // are for this table.  Then add their values to the $values array.
   foreach ($field_vals as $field_name => $items) {
-
     if (preg_match('/^' . $tablename . '__(.*)/', $field_name, $matches)) {
       $chado_field = $matches[1];
 
@@ -184,16 +181,21 @@ function tripal_fields_field_storage_write_recursive($entity_type, $entity,
         continue;
       }
 
+      // If the value is empty then exclude this field
+      if (!$items[0]['value']) {
+        continue;
+      }
+
       // Add the value of the field to the $values arr for later insert/update.
       $values[$chado_field] = $items[0]['value'];
     }
   }
-
   // STEP 3: Insert/Update the record.
   // If there are no values then return.
   if (count($values) == 0) {
     return $record_id;
   }
+
   // If we don't have an incoming record ID then this is an insert.
   if ($record_id == NULL) {
     // STEP 3a: Before inserting, we want to make sure the record does not
@@ -212,23 +214,6 @@ function tripal_fields_field_storage_write_recursive($entity_type, $entity,
       throw new Exception('Could not insert Chado record into table: "' . $tablename . '".');
     }
     $record_id = $record[$pkey_field];
-
-    // Add a record to the chado_entity table so that the data for the
-    // fields can be pulled from Chado when loaded the next time. Only do
-    // this for the base table record.
-      if ($depth == 0) {
-        $record = array(
-          'entity_id' => $entity->id,
-          'record_id' => $record_id,
-          'data_table' => $tablename,
-          'type_table' => $tablename, // TODO: this must be fixed.
-          'field' => $type_field,
-        );
-        $success = drupal_write_record('chado_entity', $record);
-        if (!$success) {
-          drupal_set_message('Unable to insert new Chado entity.', 'error');
-        }
-      }
   }
   // We have an incoming record_id so this is an update.
   else {
@@ -311,6 +296,8 @@ function tripal_fields_field_storage_load($entity_type, $entities, $age,
 
       // Type 1: fields from base tables.
       if ($field_table == $base_table) {
+        // Set an empty value by default, and if there is a record, then update.
+        $entity->{$field_name}['und'][0]['value'] = '';
         if ($record and property_exists($record, $field_column)) {
           $entity->{$field_name}['und'][0]['value'] = $record->$field_column;
         }
@@ -320,7 +307,7 @@ function tripal_fields_field_storage_load($entity_type, $entities, $age,
         $load_function = $field_module . '_' . $field_type . '_field_load';
         module_load_include('inc', $field_module, 'includes/fields/' . $field_type);
         if (function_exists($load_function)) {
-          $load_function($field, $entity, $record);
+          $load_function($field, $entity, $base_table, $record);
         }
       }
 
@@ -328,10 +315,12 @@ function tripal_fields_field_storage_load($entity_type, $entities, $age,
       // of form elements that might need populating so we'll offload the
       // loading of these fields to the field itself.
       if ($field_table != $base_table) {
+        // Set an empty value by default, and let the hook function update it.
+        $entity->{$field_name}['und'][0]['value'] = '';
         $load_function = $field_module . '_' . $field_type . '_field_load';
         module_load_include('inc', $field_module, 'includes/fields/' . $field_type);
         if (function_exists($load_function)) {
-          $load_function($field, $entity, $record);
+          $load_function($field, $entity, $base_table, $record);
         }
       }
 

+ 1 - 2
tripal_fields/tripal_fields.module

@@ -190,7 +190,6 @@ function tripal_fields_field_formatter_view($entity_type, $entity, $field,
 
       $element = array();
       switch ($display['type']) {
-
         case 'tripal_fields_organism_formatter':
           module_load_include('inc', 'tripal_fields', 'includes/fields/organism_id');
           tripal_fields_organism_select_formatter($element, $entity_type, $entity, $field,
@@ -285,6 +284,7 @@ function tripal_fields_field_widget_form(&$form, &$form_state, $field,
  * Implements hook_field_is_empty().
  */
 function tripal_fields_field_is_empty($item, $field) {
+
   // If there is no value field then the field is empty.
   if (!array_key_exists('value', $item)) {
     return TRUE;
@@ -306,7 +306,6 @@ function tripal_fields_field_is_empty($item, $field) {
  * Returns the values of the field from the $form_state.
  */
 function tripal_fields_get_field_form_values($field_name, $form_state, $delta = 0, $child = NULL) {
-
   $value = NULL;
   // The form_state must have the 'values' key. If not then just return.
   if (!array_key_exists('values', $form_state)) {