Browse Source

Fixed timelastmodified, and added new hook_chado_field_alter

Stephen Ficklin 9 năm trước cách đây
mục cha
commit
703a848bef

+ 1 - 1
tripal_entities/includes/TripalEntityUIController.inc

@@ -263,7 +263,7 @@ function tripal_entity_form($form, &$form_state, $entity = NULL) {
         '#type' => 'submit',
         '#value' => t('Delete'),
         '#name' => 'delete_data',
-        '#weight' => 1000,
+        '#weight' => 1001,
       );
     }
 

+ 56 - 71
tripal_entities/includes/tripal_entities.admin.inc

@@ -426,71 +426,70 @@ function tripal_entities_add_bundle_fields($entity_type_name, $bundle_name, $cvt
       // Determine what type of field this should be.
       // Drupal data types are: https://www.drupal.org/node/159605.
       // Field types are here:  https://www.drupal.org/node/1879542
-      $field_type = '';
-      $widget_type = '';
-      $settings = array();
-      $label = '';
-      $desc = '';
 
+      // Create an array with information about this field.
+      $field_info = array(
+        'field_type' => '',
+        'widget_type' => '',
+        'settings' => array(),
+        'description' => '',
+        'label' => $label ? $label : ucwords(preg_replace('/_/', ' ', $column_name)),
+        'chado_table' => $tablename,
+        'chado_column' => $column_name
+      );
+
+      // Alter the field info array dependiing on the column details.
       switch($details['type']) {
         case 'char':
-          $field_type = 'text';
-          $widget_type = 'text_textfield';
-          $settings['max_length'] = $details['length'];
+          $field_info['field_type'] = 'text';
+          $field_info['settings']['max_length'] = $details['length'];
           break;
         case 'varchar':
-          $field_type = 'text';
-          $widget_type = 'text_textfield';
-          $settings['max_length'] = $details['length'];
+          $field_info['field_type'] = 'text';
+          $field_info['settings']['max_length'] = $details['length'];
           break;
         case 'text':
-          $field_type = 'text';
-          $widget_type = 'text_textarea';
-          $settings['max_length'] = '';
+          $field_info['field_type'] = 'text';
+          $field_info['widget_type'] = 'text_textarea';
           break;
         case 'blob':
           // not sure how to support a blob field.
           continue;
           break;
         case 'int':
-          $field_type = 'number_integer';
-          $widget_type = 'number';
+          $field_info['field_type'] = 'number_integer';
+          $field_info['widget_type'] = 'number';
           break;
         case 'float':
-          $field_type = 'number_float';
-          $widget_type = 'number';
-          $settings['precision'] = 10;
-          $settings['scale'] = 2;
-          $settings['decimal_separator'] = '.';
+          $field_info['field_type'] = 'number_float';
+          $field_info['widget_type'] = 'number';
+          $field_info['settings']['precision'] = 10;
+          $field_info['settings']['scale'] = 2;
+          $field_info['settings']['decimal_separator'] = '.';
           break;
         case 'numeric':
-          $field_type = 'number_decimal';
-          $widget_type = 'number';
+          $field_info['field_type'] = 'number_decimal';
+          $field_info['widget_type'] = 'number';
           break;
         case 'serial':
           // Serial fields are most likely not needed as a field.
           break;
         case 'boolean':
-          $field_type = 'list_boolean';
-          $widget_type = 'options_onoff';
-          $settings['allowed_values'] = array(0 => "No", 1 => "Yes");
+          $field_info['field_type'] = 'list_boolean';
+          $field_info['widget_type'] = 'options_onoff';
+          $field_info['settings']['allowed_values'] = array(0 => "No", 1 => "Yes");
           break;
         case 'datetime':
           // Use the Drupal Date and Date API to create the field/widget
-          $field_type = 'datetime';
-          $widget_type = 'date_select';
+          $field_info['field_type'] = 'datetime';
+          $field_info['widget_type'] = 'date_select';
+          // TODO: Add settings so that the minutes increment by 1.
+          // And turn off the timezone, as the Chado field doesn't support it.
           break;
-        default:
-          drupal_set_message(t("Unhandled field type: %type", array('%type' => $details['type'])), 'warning');
-          $field_type = 'text';
-          $widget_type = 'text_textarea';
-          if (array_key_exists('length', $details)) {
-            $settings['max_length'] = $details['length'];
-          }
       }
 
       // If we don't have a field type then we don't need to create a field.
-      if (!$field_type) {
+      if (!$field_info['field_type']) {
         // If we don't have a field type but it is required and doesn't have
         // a default value then we are in trouble.
         if ($is_required and !array_key_exists('default', $details)) {
@@ -511,47 +510,20 @@ function tripal_entities_add_bundle_fields($entity_type_name, $bundle_name, $cvt
         }
       }
 
-      // If this column is a FK relationship then use a custom Tripal
-      // defined field type for it.
-      if ($is_fk) {
-        // TODO: We need a better way to get the fields for FK relationships.
-        // It's not a good idea to enumerate them all here. We need some sort
-        // of hook or something that will let us lookup the correct field.
-        switch ($column_name) {
-          case 'organism_id':
-            $field_type = 'organism_id';
-            $label = 'Organism';
-            $desc = 'Select an organism.';
-            $widget_type = 'tripal_entities_organism_select_widget';
-            break;
-          case 'dbxref_id':
-            $field_type = 'dbxref_id';
-            $label = 'Primary Cross Reference';
-            $desc = '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.';
-            $widget_type = 'tripal_entities_primary_dbxref_widget';
-            break;
-        }
-      }
-
-      // If this column is the md5checksum
-      if ($column_name == 'md5checksum') {
-        $field_type = 'md5checksum';
-        $label = 'MD5 Checksum';
-        $desc = 'Generating MD5 checksum for the sequence.';
-        $widget_type = 'tripal_entities_md5checksum_checkbox_widget';
-      }
+      // Allow other modules to alter the field information array.
+      drupal_alter('chado_field', $field_info);
 
       // If the field doesn't exist then create it.
       if (!$field) {
         $field = array(
           'field_name' => $field_name,
-          'type' => $field_type,
+          'type' => $field_info['field_type'],
           'cardinality' => 1,
           'locked' => FALSE,
           'storage' => array(
             'type' => 'field_chado_storage'
           ),
-          'settings' => $settings,
+          'settings' => $field_info['settings'],
         );
         field_create_field($field);
       }
@@ -559,21 +531,34 @@ function tripal_entities_add_bundle_fields($entity_type_name, $bundle_name, $cvt
       // Attach the field to the bundle.
       $field_instance = array(
         'field_name' => $field_name,
-        'label' => $label ? $label : ucwords(preg_replace('/_/', ' ', $column_name)),
-        'description' => $desc,
+        'label' => $field_info['label'],
+        'description' => $field_info['description'],
         'widget' => array(
-          'type' => $widget_type,
+          'type' => $field_info['widget_type'],
           'settings' => array('display_label' => 1)
         ),
         'entity_type' => $entity_type_name,
         'required' => $is_required,
-        'settings' => $settings,
+        'settings' => $field_info['settings'],
         'bundle' => $bundle_name,
       );
       field_create_instance($field_instance);
     }
   }
 }
+
+/**
+ * Implements hook_chado_field_alter.
+ *
+ * This function is used when new Chado fields are addd to an Entity.  It
+ * allows modules to customize the field, widget types and settings for
+ * a field before it is created.
+ *
+ * @param $field
+ */
+function hook_chado_field_alter(&$field) {
+  // TODO: add example code for how to use this hook.
+}
 /**
  *
  * @param unknown $form

+ 62 - 5
tripal_entities/includes/tripal_entities.chado_entity.inc

@@ -52,16 +52,73 @@ function tripal_entities_entity_delete($entity, $type) {
    ->condition('entity_id', $entity->id)
    ->execute()
    ->fetchObject();
-  
+
   if ($record && property_exists($record, 'chado_entity_id')) {
     // Delete the corresponding record in Chado
     $table = $record->data_table;
-    $record_id = $record->record_id;  
+    $record_id = $record->record_id;
     chado_delete_record($table, array($table . '_id' => $record_id));
-  
+
     //Delete the record in the public.chado_entity table
     $sql = "DELETE FROM {chado_entity} WHERE chado_entity_id = :id";
     db_query($sql, array(':id' => $record->chado_entity_id));
   }
-  
-}
+}
+
+/**
+ *
+ * @param unknown $display
+ * @param unknown $context
+ */
+function tripal_entities_field_widget_form_alter(&$element, &$form_state, $context) {
+  // The timelastmodified field exists in many Chado tables.  We want
+  // the form element to update to the most recent time rather than the time
+  // in the database.
+  if (array_key_exists('#field_name', $element)) {
+    $field_name = $element['#field_name'];
+    $matches = array();
+    if (preg_match('/(.+?)__(.+?)$/', $field_name, $matches)) {
+      $tablename = $matches[1];
+      $colname = $matches[2];
+      $schema = chado_get_schema($tablename);
+      if ($colname == 'timelastmodified' and
+          $schema['fields'][$colname]['type'] == 'datetime') {
+        $element['#default_value']['value'] = format_date(time(), 'custom', "Y-m-d H:i:s");
+        $element['#date_items']['value'] = $element['#default_value']['value'];
+        $form_state['rebuild'] = TRUE;
+      }
+    }
+  }
+}
+/**
+ * Implements hook_chado_field_alter().
+ *
+ */
+function tripal_entities_chado_field_alter($field) {
+
+  // Here we provide new field types and widgets for FK fields
+  // and fields that need special attention.
+  if ($field['chado_column'] =='organism_id') {
+    $field['field_type'] = 'organism_id';
+    $field['widget_type'] = 'tripal_entities_organism_select_widget';
+    $field['label'] = 'Organism';
+    $field['description'] = 'Select an organism.';
+  }
+  else if ($field['chado_column'] =='dbxref_id') {
+    $field['field_type'] = 'dbxref_id';
+    $field['widget_type'] = 'tripal_entities_primary_dbxref_widget';
+    $field['label'] = 'Primary Cross Reference';;
+    $field['description'] = '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.';
+  }
+  else if ($field['chado_table'] == 'feature' and
+           $field['chado_column'] == 'md5checksum') {
+    $field['field_type'] = 'md5checksum';
+    $field['widget_type'] = 'tripal_entities_md5checksum_checkbox_widget';
+    $field['label'] = 'MD5 Checksum';
+    $field['description'] = 'Generating MD5 checksum for the sequence.';
+  }
+  else if ($field['chado_table'] == 'feature' and
+           $field['chado_column'] == 'seqlen') {
+
+  }
+}

+ 15 - 21
tripal_entities/includes/tripal_entities.field_storage.inc

@@ -25,13 +25,9 @@ function tripal_entities_field_storage_query($query) {
  */
 function tripal_entities_field_storage_write($entity_type, $entity, $op, $fields) {
 
-  // Conver the fields into a key/value list of fields and their values.
+  // Convert the fields into a key/value list of fields and their values.
   $field_vals = tripal_entities_field_storage_unnest_fields($fields, $entity_type, $entity);
-  // Calculate the md5 checksum for the sequence per user's request
-  if (key_exists('feature__md5checksum', $field_vals) && key_exists('feature__residues', $field_vals)) {
-    $residues = $field_vals['feature__residues'];
-    $field_vals['feature__md5checksum'] = $field_vals['feature__md5checksum'] ? md5($residues) : NULL;
-  }
+
   switch ($op) {
     case FIELD_STORAGE_INSERT:
       // Use the cvterm_id to look up tables where this term is used
@@ -79,9 +75,6 @@ function tripal_entities_field_storage_write($entity_type, $entity, $op, $fields
 function tripal_entities_field_storage_write_recursive($entity_type, $entity,
    $op, $field_vals, $tablename, $type_field = NULL, $record_id = NULL, $depth = 0) {
 
-  dpm(array($record_id, $tablename, $field_vals));
-
-
   // Intialize the values array and $record_id;
   $values = array();
 
@@ -112,16 +105,18 @@ function tripal_entities_field_storage_write_recursive($entity_type, $entity,
       $fk_field_name = $tablename . '__' . $local_id;
       $fk_val = array_key_exists($fk_field_name, $field_vals) ? $field_vals[$fk_field_name] : NULL;
 
-      // If the value of the field is 0 then the user specifically set this
-      // value to be ignore (i.e in a select box). Don't recurse.
-      if ($fk_val != 0) {
-        // Recurse on the FK field.  Pass in the ID for the FK field if one
-        // exists in the $field_vals;
-        $fk_val = tripal_entities_field_storage_write_recursive($entity_type,
-          $entity, $op, $field_vals, $fk_table, NULL, $fk_val, $depth + 1);
-        if (isset($fk_val) and $fk_val != '') {
-          $values[$local_id] = $fk_val;
-        }
+      // Don't recurse if the value of the FK field is set to NULL.  The
+      // Tripal Chado API value for NULL is '__NULL__'.
+      if ($fk_val == "__NULL__") {
+        $values[$local_id] = $fk_val;
+        continue;
+      }
+      // Recurse on the FK field.  Pass in the ID for the FK field if one
+      // exists in the $field_vals;
+      $fk_val = tripal_entities_field_storage_write_recursive($entity_type,
+        $entity, $op, $field_vals, $fk_table, NULL, $fk_val, $depth + 1);
+      if (isset($fk_val) and $fk_val != '') {
+        $values[$local_id] = $fk_val;
       }
     }
   }
@@ -155,7 +150,6 @@ function tripal_entities_field_storage_write_recursive($entity_type, $entity,
     }
   }
 
-  dpm($values);
   // STEP 3: Insert/Update the record.
   // If there are no values then return.
   if (count($values) == 0) {
@@ -201,7 +195,7 @@ function tripal_entities_field_storage_write_recursive($entity_type, $entity,
   else {
     $match[$pkey_field] = $record_id;
     if (!chado_update_record($tablename, $match, $values)) {
-      drupal_set_message('Could not update Chado record for in table, "$table".', 'error');
+      drupal_set_message("Could not update Chado record in table: $tablename.", 'error');
     }
   }
   return $record_id;

+ 9 - 5
tripal_entities/includes/tripal_entities.fields.inc

@@ -316,14 +316,18 @@ function tripal_entities_primary_dbxref_widget_validate($element, &$form_state)
   // If user did not select a database, we want to remove dbxref_id from the
   // field.
   if (count($db_id) == 0) {
-    tripal_entities_set_field_form_values($field_name, $form_state, '__NULL__', 'dbxref__dbxref_id');
+    tripal_entities_set_field_form_values($field_name, $form_state, '__NULL__', $field_name);
   }
 }
 /**
  * Callback function for validating the tripal_entities_md5checksum_checkbox_widget.
  */
 function tripal_entities_md5checksum_checkbox_widget_validate($element, &$form_state) {
-
+  // Calculate the md5 checksum for the sequence per user's request
+  if (key_exists('feature__md5checksum', $field_vals) && key_exists('feature__residues', $field_vals)) {
+    $residues = $field_vals['feature__residues'];
+    $field_vals['feature__md5checksum'] = $field_vals['feature__md5checksum'] ? md5($residues) : NULL;
+  }
 }
 /**
  * Theme function for the primary_dbxref_widget.
@@ -372,15 +376,15 @@ function tripal_entities_get_field_form_values($field_name, $form_state, $child
 /**
  * Returns the values of the field from the $form_state.
  */
-function tripal_entities_set_field_form_values($field_name, &$form_state, $value, $child = NULL) {
+function tripal_entities_set_field_form_values($field_name, &$form_state, $newvalue, $child = NULL) {
   $values = array();
   foreach ($form_state['values'][$field_name] as $langcode => $items) {
     foreach ($items as $delta => $value) {
       if ($child and array_key_exists($child, $value['value'][0]) and $value['value'][0][$child]) {
-        $form_state['values'][$field_name][$langcode][$delta]['value'][0][$child] = $value;
+        $form_state['values'][$field_name][$langcode][$delta]['value'][0][$child] = $newvalue;
       }
       else if (!$child and $value['value']) {
-        $form_state['values'][$field_name][$langcode][$delta]['value'] = $value;
+        $form_state['values'][$field_name][$langcode][$delta]['value'] = $newvalue;
       }
     }
   }