Browse Source

Fixed issue with uploader. Added support for cvterm as a base table. Fixed bugs with OBO loader

Stephen Ficklin 7 years ago
parent
commit
4889b3fae7

+ 1 - 1
tripal/includes/TripalImporter.inc

@@ -288,7 +288,7 @@ class TripalImporter {
       }
 
       // Validate the $file_details argument.
-      if ($has_file == 0 and $class::file_required == TRUE) {
+      if ($has_file == 0 and $class::$file_required == TRUE) {
         throw new Exception("Must provide a proper file identifier for the \$file_details argument.");
       }
 

+ 1 - 0
tripal/includes/tripal.importer.inc

@@ -94,6 +94,7 @@ function tripal_get_importer_form($form, &$form_state, $class) {
  * Validate function for the tripal_get_importer_form form().
  */
 function tripal_get_importer_form_validate($form, &$form_state) {
+
   $class = $form_state['values']['importer_class'];
   tripal_load_include_importer_class($class);
 

+ 2 - 2
tripal/includes/tripal.upload.inc

@@ -136,12 +136,12 @@ function tripal_file_upload_merge($filename, $type, $user_dir) {
       }
       else {
         $status = 'failed';
-        $message = 'Could not add file to GenSAS database.';
+        $message = 'Could not add file to the database.';
       }
     }
     else {
       $status = 'failed';
-      $message = 'Requesting module does not implement hook_handle_uploaded_file.';
+      $message = 'Cannot find the function: ' . $function . '().';
     }
   }
 

+ 1 - 1
tripal/theme/js/TripalUploader.js

@@ -559,7 +559,7 @@
               // by their index. The file with an index of 0 is always ordered first.
               'i': index,
               // The URL at the remote server where the file will uploaded. 
-              'url' : '/tripal/upload/' + category,
+              'url' : baseurl + '/tripal/upload/' + category,
             };
             self.addFile(f, options);
 

+ 14 - 9
tripal/tripal.module

@@ -856,7 +856,7 @@ function tripal_element_info() {
   // accepts the following keys when using in a form:
   //   - #title:  The title that will appear above the element.
   //   - #description:  The description that will appear below the element.
-  //   - #usage_type:  Required.  The type of file.  Thie will be stored in
+  //   - #usage_type:  Required.  The type of file.  This will be stored in
   //     the 'type' column of the file_usage table.
   //   - #usage_id: Required. A unique numeric ID representing an entity, node
   //     or some other record identifier.  This can be any identifier that
@@ -875,10 +875,10 @@ function tripal_element_info() {
  *  The process function for the html5_file form element.
  */
 function tripal_html5_file_process($element, $form_state, $complete_form) {
-//   $nid = $element['#webform_component']['nid'];
-//   $form_key = $element['#webform_component']['form_key'];
+
   $type = $element['#usage_id'] . '-' . $element['#usage_type'];
   $name = $element['#name'];
+  $name = preg_replace('/[^\w]/', '_', $name);
 
   $headers = array(
     array('data' => 'File'),
@@ -898,10 +898,6 @@ function tripal_html5_file_process($element, $form_state, $complete_form) {
     'colgroups'   => array(),
     'empty'       => t('There are currently no files.'),
   );
-  $element['value'] = array(
-    '#type' => 'value',
-    '#value' => '',
-  );
   $element['html5_file_table_key'] = array(
     '#type' => 'hidden',
     '#value' => $type,
@@ -915,6 +911,7 @@ function tripal_html5_file_process($element, $form_state, $complete_form) {
     '#description' => $element['#description'],
     '#markup' => theme('table', $table_vars)
   );
+
   $element[$name] = array(
     '#type' => 'hidden',
     '#attributes' => array('id' => 'tripal-html5-upload-fid-' . $type),
@@ -988,10 +985,18 @@ function tripal_handle_uploaded_file($filename, $filepath, $type) {
 }
 
 /**
- *
+ * Implements hook_value() for the html5_file form element.
  */
 function tripal_html5_file_value($element, $input = FALSE, &$form_state) {
+
   if ($input) {
-    return $input;
+    if (is_array($input)) {
+      $name = $element['#name'];
+      $name = preg_replace('/[^\w]/', '_', $name);
+      return $input[$name];
+    }
+    else {
+      return $input;
+    }
   }
 }

+ 18 - 0
tripal_chado/api/tripal_chado.api.inc

@@ -114,6 +114,24 @@ function tripal_chado_publish_records($values, $job_id = NULL) {
     $args[':cvterm_id'] = $cvterm_id;
   }
 
+  // Handle the case where records are in the cvterm table and mapped via a single
+  // vocab.  Here we use the type_value for the cv_id.
+  if ($table == 'cvterm' and $type_value) {
+    $where .= "AND T.cv_id = :cv_id";
+    $args[':cv_id'] = $type_value;
+  }
+
+  // Handle the case where records are in the cvterm table but we want to
+  // use all of the child terms.
+  if ($table == 'cvterm' and !$type_value) {
+    $where .= "AND T.cvterm_id IN (
+       SELECT CVTS.cvterm_id
+       FROM {cvtermpath} CVTP
+       WHERE CVTP.object_id = :cvterm_id)
+     ";
+    $args[':cvterm_id'] = $cvterm_id;
+  }
+
   // Now add in any additional filters
   $fields = field_info_field_map();
   foreach ($fields as $field_name => $details) {

+ 7 - 0
tripal_chado/api/tripal_chado.schema.api.inc

@@ -594,6 +594,13 @@ function chado_get_base_tables() {
     }
   }
 
+  // Remove the phenotype table. It really shouldn't be a base table as
+  // it is meant to store individual phenotype measurements.
+  unset($final_list['phenotyp']);
+
+  // Now add in the cvterm table to the list.
+  $final_list[] = 'cvterm';
+
   // Sort the tables and return the list.
   sort($final_list);
   return $final_list;

+ 112 - 0
tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary.inc

@@ -0,0 +1,112 @@
+<?php
+
+class sio__vocabulary extends ChadoField {
+
+  // The default lable for this field.
+  public static $default_label = 'Vocabulary';
+
+  // The default description for this field.
+  public static $description = 'The vocabulary to which this resource is associated.';
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  // If you override this variable in a child class be sure to replicate the
+  // term_name, term_vocab, term_accession and term_fixed keys as these are
+  // required for all TripalFields.
+  public static $default_instance_settings  = array(
+    // The short name for the vocabulary (e.g. shcema, SO, GO, PATO, etc.).
+    'term_vocabulary' => 'SIO',
+    // The name of the term.
+    'term_name' => 'vocabulary',
+    // The unique ID (i.e. accession) of the term.
+    'term_accession' => '001080',
+    // Set to TRUE if the site admin is allowed to change the term
+    // type. This will create form elements when editing the field instance
+    // to allow the site admin to change the term settings above.
+    'term_fixed' => FALSE,
+  );
+
+  // The default widget for this field.
+  public static $default_widget = 'sio__vocabulary_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'sio__vocabulary_formatter';
+
+
+  /**
+   * @see TripalField::validate()
+   */
+  public function validate($entity_type, $entity, $field, $items, &$errors) {
+
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
+
+    // Get the field values.
+    foreach ($items as $delta => $values) {
+
+      // Get the field values.
+      $cv_id = $values['chado-' . $field_table . '__cv_id'];
+      if (!$cv_id or $cv_id == 0) {
+        $errors[$field_name]['und'][0][] = array(
+          'message' =>  t("Please specify a vocabulary."),
+          'error' => 'chado-' . $field_table . '__cv_id'
+        );
+      }
+    }
+  }
+
+  /**
+   * @see TripalField::load()
+   */
+  public function load($entity) {
+
+    $record = $entity->chado_record;
+    $settings = $this->instance['settings'];
+
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
+
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = array(
+      'value' => array(),
+    );
+
+    if ($record) {
+      $cv = $record->cv_id;
+      $entity->{$field_name}['und'][0]['value'] = $cv->name;
+      $entity->{$field_name}['und'][0]['chado-' . $field_table . '__cv_id'] = $cv->cv_id;
+    }
+  }
+
+  /**
+   * @see ChadoField::query()
+   */
+  public function query($query, $condition) {
+    $alias = $this->field['field_name'];
+    $operator = $condition['operator'];
+
+    $query->join('cv', $alias, "base.cv_id = $alias.cv_id");
+    $query->condition("$alias.name", $condition['value'], $operator);
+  }
+
+  /**
+   * @see ChadoField::queryOrder()
+   */
+  public function queryOrder($query, $order) {
+
+    // If the table hasn't yet been joined then add it.
+    $joins = $query->getTables();
+    if (!in_array($this->field['field_name'], $joins)) {
+      $alias = $this->field['field_name'];
+      $query->join('cv', $alias, "base.cv_id = $alias.cv_id");
+      $query->orderBy("$alias.name", $order['direction']);
+    }
+  }
+}

+ 24 - 0
tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary_formatter.inc

@@ -0,0 +1,24 @@
+<?php
+
+class sio__vocabulary_formatter extends ChadoFieldFormatter {
+
+  // The default lable for this field.
+  public static $default_label = 'Vocabulary';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('sio__vocabulary');
+
+  /**
+   * @see TripalFieldFormatter::view()
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+    if (count($items) > 0) {
+      // The cardinality of this field is 1 so we don't have to
+      // iterate through the items array, as there will never be more than 1.
+      $element[0] = array(
+        '#type' => 'markup',
+        '#markup' => $items[0]['value'],
+      );
+    }
+  }
+}

+ 54 - 0
tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary_widget.inc

@@ -0,0 +1,54 @@
+<?php
+
+class sio__vocabulary_widget extends ChadoFieldWidget {
+
+  // The default lable for this field.
+  public static $default_label = 'Vocabulary';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('sio__vocabulary');
+
+
+  /**
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
+
+    $cv_id = 0;
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+    $widget['chado-' . $field_table . '__cv_id'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['chado-' . $field_table . '__cv_id'],
+    );
+    $widget['vocabulary_name'] = array(
+      '#type' => 'item',
+      '#title' => 'Vocabulary',
+      '#markup' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+  }
+
+  /**
+   * @see TripalFieldWidget::validate()
+   */
+  public function validate($element, $form, &$form_state, $langcode, $delta) {
+
+    $field_name = $this->field['field_name'];
+    $field_table = $this->instance['settings']['chado_table'];
+
+    // Make sure the value is set to the cv_id
+    $cv_id = $form_state['values'][$field_name][$langcode][0]['chado-' . $field_table . '__cv_id'];
+    $form_state['values'][$field_name][$langcode][0]['value'] = $cv_id;
+  }
+}

+ 10 - 9
tripal_chado/includes/TripalImporter/OBOImporter.inc

@@ -271,10 +271,10 @@ class OBOImporter extends TripalImporter {
         ->condition('obo_id', $obo_id)
         ->execute();
       if ($success) {
-        drupal_set_message(t("The vocabulary %vocab has been updated.", array('%vocab' => $uobo_name)));
+        drupal_set_message(t("The vocabulary !vocab has been updated.", array('!vocab' => $uobo_name)));
       }
       else {
-        drupal_set_message(t("The vocabulary %vocab could not be updated.", array('%vocab' => $uobo_name)), 'error');
+        drupal_set_message(t("The vocabulary !vocab could not be updated.", array('!vocab' => $uobo_name)), 'error');
       }
 
     }
@@ -287,12 +287,12 @@ class OBOImporter extends TripalImporter {
         ->execute();
         // Add the obo_id to the form_state vaules.
         $form_state['values']['obo_id'] = $obo_id;
-      if ($success) {
-        drupal_set_message(t("The vocabulary %vocab has been added.", array('%vocab' => $obo_name)));
+      if ($obo_id) {
+        drupal_set_message(t("The vocabulary !vocab has been added.", array('!vocab' => $obo_name)));
       }
       else {
         $form_state['rebuild'] = TRUE;
-        drupal_set_message(t("The vocabulary %vocab could not be added.", array('%vocab' => $obo_name)), 'error');
+        drupal_set_message(t("The vocabulary !vocab could not be added.", array('!vocab' => $obo_name)), 'error');
       }
     }
   }
@@ -592,10 +592,11 @@ class OBOImporter extends TripalImporter {
       else {
         throw new Exception("Could not find a namespace for this OBO file: $file");
       }
-      $this->logMessage("This OBO is missing the 'default-namespace' header. It is not possible to determine which vocabulary terms without a 'namespace' key should go.  Instead, those terms will be placed in the '%vocab' vocabulary.",
-          array('%vocab' => $defaultcv->name), TRIPAL_WARNING);
-    }
-
+      $this->logMessage("This OBO is missing the 'default-namespace' header. It " .
+          "is not possible to determine which vocabulary terms without a 'namespace' key " .
+          "should go.  Instead, those terms will be placed in the '!vocab' vocabulary.",
+          array('!vocab' => $defaultcv->name), TRIPAL_WARNING);
+    }!
     // add any typedefs to the vocabulary first
     $this->logMessage("Step 2: Loading type defs...");
     $this->loadTypeDefs($defaultcv, $newcvs, $default_db);

+ 6 - 0
tripal_chado/includes/tripal_chado.entity.inc

@@ -177,6 +177,12 @@ function tripal_chado_tripal_default_title_format($bundle, $available_tokens) {
       'weight' => -5,
     );
   }
+  if ($table == 'cvterm') {
+    $format[] = array(
+      'format' => '[schema__name]',
+      'weight' => -5,
+    );
+  }
   return $format;
 }
 

+ 118 - 5
tripal_chado/includes/tripal_chado.field_storage.inc

@@ -640,6 +640,8 @@ function tripal_chado_field_storage_bundle_mapping_form($form, &$form_state,
   $default = array(
     'table' => '',
     'has_all' => 'No',
+    'use_cvterm' => 'cv',
+    'cv_id' => '',
     'use_linker' => 'Yes',
     'use_prop' => 'Yes',
     'type_column' => '',
@@ -680,6 +682,14 @@ function tripal_chado_field_storage_bundle_mapping_form($form, &$form_state,
       and $form_state['values']['prop_term_value']) {
     $default['prop_term_value'] = $form_state['values']['prop_term_value'];
   }
+  if (array_key_exists('chado_type_use_cv', $form_state['values'])
+      and $form_state['values']['chado_type_use_cv']) {
+    $default['use_cvterm'] = $form_state['values']['chado_type_use_cv'];
+  }
+  if (array_key_exists('chado_type_cv_id', $form_state['values'])
+      and $form_state['values']['chado_type_cv_id']) {
+    $default['cv_id'] = $form_state['values']['chado_type_cv_id'];
+  }
 
   $form['selected_cvterm_id'] = array(
     '#type' => 'value',
@@ -714,6 +724,16 @@ function tripal_chado_field_storage_bundle_mapping_form($form, &$form_state,
   // Get the schema for this table.
   $schema = chado_get_schema($default['table']);
 
+  // If the selected base table is 'cvterm' then handle it specially.
+  if ($default['table'] == 'cvterm') {
+    tripal_chado_field_storage_bundle_mapping_form_add_cvterm($form,
+        $form_state, $term, $default);
+    if ($default['cv_id']) {
+      $submit_disabled = FALSE;
+    }
+    return $form;
+  }
+
   // Ask the user if all of the records in the default table are of one type.
   tripal_chado_field_storage_bundle_mapping_form_add_allrecs($form,
       $form_state, $term, $default);
@@ -787,6 +807,9 @@ function tripal_chado_field_storage_bundle_mapping_form($form, &$form_state,
   return $form;
 }
 
+/**
+ *
+ */
 function tripal_chado_field_storage_bundle_mapping_form_add_type(&$form,
     &$form_state, $term, &$default){
 
@@ -834,6 +857,9 @@ function tripal_chado_field_storage_bundle_mapping_form_add_type(&$form,
   }
 }
 
+/**
+ *
+ */
 function tripal_chado_field_storage_bundle_mapping_form_add_allrecs(&$form,
     &$form_state, $term, $default) {
 
@@ -861,6 +887,9 @@ function tripal_chado_field_storage_bundle_mapping_form_add_allrecs(&$form,
   );
 }
 
+/**
+ *
+ */
 function tripal_chado_field_storage_bundle_mapping_form_add_linker(&$form,
     &$form_state, $term, $linker_table, $default){
 
@@ -885,7 +914,9 @@ function tripal_chado_field_storage_bundle_mapping_form_add_linker(&$form,
     ),
   );
 }
-
+/**
+ *
+ */
 function tripal_chado_field_storage_bundle_mapping_form_add_prop(&$form,
     &$form_state, $term, $prop_table, $default){
 
@@ -997,6 +1028,55 @@ function tripal_chado_field_storage_bundle_mapping_form_add_prop(&$form,
     }
   }
 }
+
+/**
+ *
+ */
+function tripal_chado_field_storage_bundle_mapping_form_add_cvterm(&$form,
+    &$form_state, $term, &$default){
+
+  $form['chado_type_use_cv'] = array(
+    '#type' => 'radios',
+    '#title' => 'How do you want to distinguish the "' . $term->name . '" records
+      within the cvterm table?',
+    '#options' => array(
+      'cv' => 'All records that belong to a single controlled vocabulary?',
+      'parent' => 'All child records of the specified term?'
+    ),
+    '#description' => t('Records in the cvterm table are often not used for content
+        types. The records in the cvterm table are meant to be vocabulary terms.
+        However, there are times when records in the cvterm table can be
+        used for a content type. One example is for trait "pages" that
+        use phenotype values stored in the phenotype table.  Because records in
+        the cvterm table are vocabulary terms they do not have "types" so the
+        only ways to distinguish them are 1) to use the controlled vocabulary to
+        distinguish the records or 2) to use all children records of the
+        selected term.  Please select the appropriate value for this case.'),
+    '#default_value' => $default['use_cvterm'],
+    '#ajax' => array(
+      'callback' => "tripal_admin_add_type_form_ajax_callback",
+      'wrapper' => "tripal-vocab-select-form",
+      'effect' => 'fade',
+      'method' => 'replace'
+    ),
+  );
+  if ($default['use_cvterm'] == 'cv') {
+    $cvs = tripal_get_cv_select_options();
+    $form['chado_type_cv_id'] = array(
+      '#type' => select,
+      '#options' => $cvs,
+      '#title' => t('Select a controlled vocabulary'),
+      '#default_value' => $default['cv_id'],
+      '#ajax' => array(
+        'callback' => "tripal_admin_add_type_form_ajax_callback",
+        'wrapper' => "tripal-vocab-select-form",
+        'effect' => 'fade',
+        'method' => 'replace'
+      ),
+    );
+  }
+
+}
 /**
  * Implements hook_field_stoage_bundle_mapping_form_validate().
  */
@@ -1005,6 +1085,8 @@ function tripal_chado_field_storage_bundle_mapping_form_validate($form, &$form_s
   $default = array(
     'table' => '',
     'has_all' => 'No',
+    'use_cvterm' => 'cv',
+    'cv_id' => '',
     'use_linker' => 'Yes',
     'use_prop' => 'Yes',
     'type_column' => '',
@@ -1058,14 +1140,19 @@ function tripal_chado_field_storage_bundle_mapping_form_validate($form, &$form_s
       and $form_state['values']['prop_term_value']) {
     $default['prop_term_value'] = $form_state['values']['prop_term_value'];
   }
+  if (array_key_exists('chado_type_use_cv', $form_state['values'])
+      and $form_state['values']['chado_type_use_cv']) {
+    $default['use_cvterm'] = $form_state['values']['chado_type_use_cv'];
+  }
+  if (array_key_exists('chado_type_cv_id', $form_state['values'])
+      and $form_state['values']['chado_type_cv_id']) {
+    $default['cv_id'] = $form_state['values']['chado_type_cv_id'];
+  }
 
   // Make sure a default table is selected
   if (!$default['table']) {
     form_set_error('base_chado_table', 'Please select a default table.');
   }
-
-
-
 }
 /**
  * Implements hook_field_stoage_bundle_mapping_form_submit().
@@ -1080,6 +1167,8 @@ function tripal_chado_field_storage_bundle_mapping_form_submit($form,
   $default = array(
     'table' => '',
     'has_all' => 'No',
+    'use_cvterm' => 'cv',
+    'cv_id' => '',
     'use_linker' => 'No',
     'use_prop' => 'No',
     'type_column' => '',
@@ -1114,15 +1203,37 @@ function tripal_chado_field_storage_bundle_mapping_form_submit($form,
       and $form_state['values']['prop_term_value']) {
     $default['prop_term_value'] = $form_state['values']['prop_term_value'];
   }
+  if (array_key_exists('chado_type_use_cv', $form_state['values'])
+      and $form_state['values']['chado_type_use_cv']) {
+    $default['use_cvterm'] = $form_state['values']['chado_type_use_cv'];
+  }
+  if (array_key_exists('chado_type_cv_id', $form_state['values'])
+      and $form_state['values']['chado_type_cv_id']) {
+    $default['cv_id'] = $form_state['values']['chado_type_cv_id'];
+  }
+
+  // If the user selected to use the cvterm table then we have to
+  // handle it specially.
+  if ($default['use_cvterm']) {
+    $storage_args['data_table'] = $default['table'];
+    $storage_args['type_id'] = $form_state['values']['selected_cvterm_id'];
+    $storage_args['type_value'] = '';
+    if ($default['cv_id']) {
+      $storage_args['type_value'] = $default['cv_id'];
+    }
+    $storage_args['type_column'] = '';
+
+    return;
+  }
 
   // If we have a type_column then we know this type uses a column in the
   // base table, so we can set the storage args and return.
   if ($default['type_column']) {
     $storage_args['data_table'] = $default['table'];
-    $storage_args['type_id'] = $form_state['values']['selected_cvterm_id'];
     $storage_args['type_column'] = $default['type_column'];
     return;
   }
+
   // If the user indicated that all the records in a table are of this type.
   if ($default['has_all'] == 'Yes') {
     $storage_args['data_table'] = $default['table'];
@@ -1151,3 +1262,5 @@ function tripal_chado_field_storage_bundle_mapping_form_submit($form,
     $storage_args['type_column'] = 'cvterm_id';
   }
 }
+
+

+ 53 - 0
tripal_chado/includes/tripal_chado.fields.inc

@@ -68,6 +68,11 @@ function tripal_chado_bundle_fields_info_base(&$info, $details, $entity_type, $b
       continue;
     }
 
+    // Skip the cvterm.is_relationshptype.
+    if ($table_name == 'cvterm' and $column_name == 'is_relationshiptype') {
+      continue;
+    }
+
     // Don't create base fields for the primary key and the type_id field.
     if ($column_name == $pkey or $column_name == $type_field) {
       continue;
@@ -214,6 +219,21 @@ function tripal_chado_bundle_fields_info_custom(&$info, $details, $entity_type,
     );
   }
 
+  // BASE ORGANISM_ID
+  if ($table_name == 'cvterm') {
+    $field_name = 'sio__vocabulary';
+    $field_type = 'sio__vocabulary';
+    $info[$field_name] = array(
+      'field_name' => $field_name,
+      'type' => $field_type,
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'field_chado_storage',
+      ),
+    );
+  }
+
   // BASE DBXREF
   if (array_key_exists('dbxref_id', $schema['fields'])) {
     $field_name = 'data__accession';
@@ -912,6 +932,39 @@ function tripal_chado_bundle_instances_info_custom(&$info, $entity_type, $bundle
     );
   }
 
+  // BASE ORGANISM_ID
+  if ($table_name == 'cvterm') {
+    $field_name = 'sio__vocabulary';
+    $is_required = TRUE;
+    $info[$field_name] =  array(
+      'field_name' => $field_name,
+      'entity_type' => $entity_type,
+      'bundle' => $bundle->name,
+      'label' => 'Vocabulary',
+      'description' => 'Select a vocabulary.',
+      'required' => $is_required,
+      'settings' => array(
+        'auto_attach' => TRUE,
+        'chado_table' => $table_name,
+        'chado_column' => 'cv_id',
+        'base_table' => $table_name,
+      ),
+      'widget' => array(
+        'type' => 'sio__vocabulary_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'default' => array(
+          'label' => 'inline',
+          'type' => 'sio__vocabulary_formatter',
+          'settings' => array(),
+        ),
+      ),
+    );
+  }
+
   // BASE DBXREF
   if (array_key_exists('dbxref_id', $schema['fields'])) {
     $field_name = 'data__accession';

+ 10 - 0
tripal_chado/includes/tripal_chado.semweb.inc

@@ -207,6 +207,15 @@ function tripal_chado_populate_vocab_SIO() {
     'definition' => 'A measurement of a spatial location relative to a frame of reference or other objects.',
   ));
   tripal_associate_chado_semweb_term('featurepos', 'mappos', $term);
+
+
+  $term = tripal_insert_cvterm(array(
+    'id' => 'SIO:001080',
+    'name' => 'vocabulary',
+    'cv_name' => 'SIO',
+    'definition' => 'A vocabulary is a collection of terms.',
+  ));
+  tripal_associate_chado_semweb_term('cvterm', 'cv_id', $term);
 }
 /**
  * Adds the EDAM database and terms.
@@ -737,6 +746,7 @@ function tripal_chado_populate_vocab_LOCAL() {
   tripal_associate_chado_semweb_term('pub_relationship', 'type_id', $term);
   tripal_associate_chado_semweb_term('quantification_relationship', 'type_id', $term);
   tripal_associate_chado_semweb_term('stock_relationship', 'type_id', $term);
+  tripal_associate_chado_semweb_term('cvterm_relationship', 'type_id', $term);
 
   //-----------------------------
   // NCBI Organism Property Terms