Browse Source

Merge branch '7.x-3.x' into 525-tv3-obo_speed_colon

Stephen Ficklin 6 years ago
parent
commit
d20f4065e2

+ 1 - 0
docs/dev_guide.rst

@@ -13,3 +13,4 @@ Developer's Guide
    dev_guide/custom_field
    dev_guide/custom_data_loader
    dev_guide/custom_web_services
+   dev_guide/tutorials

+ 30 - 0
docs/dev_guide/tutorials.rst

@@ -0,0 +1,30 @@
+Video Tutorials
+=================
+
+.. note::
+
+
+  The following videos are provided by members of the community. While we don't ensure the videos are up to date, we would appreciate being `contacted through the issue queue <https://github.com/tripal/tripal/issues/new/choose>`_ if you find a broken link. Also, if you have your own video and would like to contribute, we would love to hear from you!
+
+
+
+Testing
+~~~~~~~~~
+
+The `Tripal Test Suite module <https://github.com/statonlab/TripalTestSuite>`_ is used by the core Tripal module, and many custom modules, to easily set up PHPUnit and Travis CI.
+
+* `Creating and running Test Suite Tests <https://www.youtube.com/watch?v=hxuiDzRqs9U>`_
+
+* `Test Driven Development live demo <https://www.youtube.com/watch?v=zmYZ_HV3b9s>`_
+
+Developer Tools
+~~~~~~~~~~~~~~~~
+
+* `Tripal 3 - Setting Up A Website From Scratch With TripalDock <https://www.youtube.com/watch?v=5SOfQLypvdE>`_
+
+* `Tripal 3 - TripalDock Commands And Site Structure <https://www.youtube.com/watch?v=g_fmONUgG3s>`_
+
+Other
+~~~~~~~
+
+* `Loading Biomaterials with Tripal Analysis Expression <https://www.youtube.com/watch?v=7YkPp2443qA>`_

+ 20 - 5
tripal/api/tripal.entities.api.inc

@@ -326,6 +326,7 @@ function tripal_load_vocab_entity($values) {
  *     - name:  the bundle name (e.g. 'bio_data_234')
  *     - label: the bundle label (e.g. 'Organism')
  *     - term_id: the term ID to which the bundle belongs
+ *     - accession: the full acccession for the bundle (e.g. OBI:0100026)
  *
  * @return
  *   A TripalBundle entity object or NULL if not found.
@@ -348,6 +349,15 @@ function tripal_load_bundle_entity($values) {
   if (array_key_exists('term_id', $values)) {
     $query->condition('tb.term_id', $values['term_id']);
   }
+  if (array_key_exists('accession', $values)) {
+    list($vocab, $accession) = explode(':', $values['accession'], 2);
+    $term = tripal_load_term_entity(['vocabulary' => $vocab, 'accession' => $accession]);
+    if (!$term) {
+      return NULL;
+    }
+    $query->condition('tb.term_id', $term->id);
+    
+  }
   $bundle = $query->execute()->fetchObject();
 
   if ($bundle) {
@@ -436,11 +446,11 @@ function tripal_create_bundle($args, $job = NULL) {
     'watchdog' => TRUE,
   ];
   
-  tripal_report_error('tripal_entities', TRIPAL_INFO, 
-   "Creation of a content type is performed using a database transaction. " .
-    "If it fails or is terminated prematurely then all insertions and " .
-    "updates are rolled back and will not be found in the database", 
-    [], $message_args);
+//   tripal_report_error('tripal_entities', TRIPAL_INFO, 
+//    "Creation of a content type is performed using a database transaction. " .
+//     "If it fails or is terminated prematurely then all insertions and " .
+//     "updates are rolled back and will not be found in the database", 
+//     [], $message_args);
 
   $transaction = db_transaction();
   try {
@@ -530,7 +540,12 @@ function tripal_create_bundle($args, $job = NULL) {
         'Unable to load Tripal Bundle :name after cache clear.', array(':name' => $bundle_name), $message_args);
       return FALSE;
     }
+    
+    // Set the bundle category
+    $category = array_key_exists('bundle_category', $args) ? $args['bundle_category'] : 'Other';
+    tripal_set_bundle_variable($variable_name, $bundle->id, $category);
 
+    // Attache the bundle fields.
     tripal_create_bundle_fields($bundle, $term);
 
     // Specifically commiting here since we have a fully featured bundle.

+ 1 - 1
tripal/api/tripal.importer.api.inc

@@ -185,7 +185,7 @@ function tripal_run_importer($import_id, TripalJob $job = NULL) {
     tripal_tripal_cron_notification();
 
     // Clear the Drupal cache
-    cache_clear_all();
+    //cache_clear_all();
   }
   catch (Exception $e) {
     if ($job) {

+ 117 - 28
tripal/includes/TripalEntityUIController.inc

@@ -604,10 +604,10 @@ function tripal_entity_form_ajax_callback($form, $form_state) {
   return $form;
 }
 
- /**
-  * Implements hook_validate() for the tripal_entity_form.
-  */
- function tripal_entity_form_validate($form, &$form_state) {
+/**
+ * Implements hook_validate() for the tripal_entity_form.
+ */
+function tripal_entity_form_validate($form, &$form_state) {
 
    // If the user is cancelling or deleting the entity then don't validate.
    if (array_key_exists('clicked_button', $form_state) and
@@ -631,12 +631,12 @@ function tripal_entity_form_ajax_callback($form, $form_state) {
    catch (Exception $e) {
      form_set_error('author_date', 'Please provide a valid authored on date.');
    }
- }
+}
 
- /**
-  * Implements hook_submit() for the tripal_entity_form.
-  */
- function tripal_entity_form_submit($form, &$form_state) {
+/**
+ * Implements hook_submit() for the tripal_entity_form.
+ */
+function tripal_entity_form_submit($form, &$form_state) {
    $entity = $form_state['TripalEntity'];
 
    if ($form_state['clicked_button']['#name'] =='cancel_data') {
@@ -691,27 +691,116 @@ function tripal_entity_form_ajax_callback($form, $form_state) {
    else {
      drupal_set_message('Cannot save entity', 'error');
    }
-
- }
+}
 
 
- /**
-  * Provides a list of TripalEntity types (bundles) for the user to add.
-  *
-  * This function is a callback in a menu item which is set in the
-  * TripalEntityUIController class.
-  */
- function tripal_add_page() {
-   $item = menu_get_item();
-   $content = system_admin_menu_block($item);
-   // Bypass the node/add listing if only one content type is available.
-   if (count($content) == 1) {
-     $item = array_shift($content);
-     drupal_goto($item['href']);
-   }
-   return theme('tripal_add_list', array('content' => $content));
-
- }
+/**
+ * Provides a list of TripalEntity types (bundles) for the user to add.
+ *
+ * This function is a callback in a menu item which is set in the
+ * TripalEntityUIController class.
+ */
+function tripal_add_page() {
+  
+  // The content array to be returned.
+  $content = [];
+   
+  $content['instructions'] = [
+    '#type' => 'markup',
+    '#markup' => 'This page provides links for creating pages for Tripal ' . 
+      'supported content types. These content types are organized by categories. ' . 
+      'Please note, however, that the categorization is the most common use ' . 
+      'for a given type. Some types may be useful in other "categories" as well.',
+    '#weight' => -15,
+  ];
+  
+
+  // Get the list of categories.
+  $select = "
+    SELECT TBV.value as category
+    FROM tripal_bundle_variables TBV
+      INNER JOIN tripal_variables TV on TV.variable_id = TBV.variable_id
+    WHERE TV.name = 'bundle_category'
+  ";
+  $categories = db_query($select);
+  
+  
+  // Build the fieldsets for the categories.
+  $fieldsets = [];
+  $category_weight = 1;
+  while ($category = $categories->fetchField()) {
+    $machine_name = preg_replace('/[^\w]/', '_', $category);
+    $fieldsets[$machine_name . '_fieldset'] = [
+      '#type' => 'fieldset',
+      '#title' => $category,
+      '#collapsed' => TRUE,
+      '#collapsible' => TRUE,
+      '#attributes' => array(
+        'class' => array('collapsible', 'tripal-content-list'),
+      ),
+      '#attached' => array(
+        'js' => array('misc/collapse.js', 'misc/form.js')
+      ),
+      '#weight' => $category == 'General' ? -10 : $category_weight++,
+    ];
+  }
+  
+  // Create the "other" fieldset, and set it's weight to 100 so it goes to
+  // the bottom.
+  $fieldsets['Other_fieldset'] = [
+    '#type' => 'fieldset',
+    '#title' => 'Other',
+    '#weight' => 100,
+    '#collapsed' => TRUE,
+    '#collapsible' => TRUE,
+    '#attributes' => array(
+      'class' => array('collapsible'),
+    ),
+    '#attached' => array(
+      'js' => array('misc/collapse.js', 'misc/form.js')
+    ),
+  ]; 
+  
+  
+  // Get the list of bundles and iterate through them.
+  $select = "SELECT id, name, label FROM tripal_bundle ORDER BY label";
+  $bundles = db_query($select);
+  while ($bundle = $bundles->fetchObject()) {
+    
+    // Lookup the bundle category.
+    $sql = "
+      SELECT TBV.value as category
+      FROM tripal_bundle TB
+        INNER JOIN tripal_bundle_variables TBV on TB.id = TBV.bundle_id
+        INNER JOIN tripal_variables TV on TV.variable_id = TBV.variable_id
+      WHERE TV.name = 'bundle_category' and TB.id = :id;
+    ";
+  
+    $category = db_query($sql, [':id' => $bundle->id])->fetchField();
+    if (!$category) {
+      $category = 'Other';
+    }
+    
+    $machine_name = preg_replace('/[^\w]/', '_', $category);
+    $bundle = tripal_load_bundle_entity(['id' => $bundle->id]);
+    if (!$bundle) {
+      continue;
+    }
+    if (user_access('create ' . $bundle->name)) {
+      if (!array_key_exists($machine_name . '_fieldset', $content)) {
+        $content[$machine_name . '_fieldset'] = $fieldsets[$machine_name . '_fieldset'];
+      }
+      $content[$machine_name . '_fieldset'][$bundle->name] = [
+        '#type' => 'item',
+        '#markup' => l($bundle->label, 'bio_data/add/' . $bundle->id),
+        '#description' => $bundle->term->definition
+      ];
+    }
+  }
+  
+  // Now iterate through the fieldsets and set their weight
+  return $content;
+}
 
  /**
   * Returns HTML for a list of available node types for node creation.

+ 1 - 1
tripal/theme/css/tripal.css

@@ -113,4 +113,4 @@ div.messages.tripal-site-admin-only {
 
 .item-list .action-links li {
 	list-style-type: none;
-} 
+} 

+ 491 - 233
tripal_chado/includes/setup/tripal_chado.setup.inc

@@ -266,143 +266,130 @@ function tripal_chado_prepare_chado($job = NULL) {
     
     drush_print("Creating common Tripal Content Types...");
     drush_print("This may take awhile if you are upgrading a site that has lots of data...");
-
-    // Create the 'Organism' entity type. This uses the obi:organism term.
-    drush_print("Creating Organism...");
-    $args = array(
-      'vocabulary' => 'OBI',
-      'accession' => '0100026',
-      'term_name' => 'organism',
-      'storage_args' => array(
-        'data_table' => 'organism',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'OBI', 'accession' => '0100026'));
-    if ($term) {
-      $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered creating "Organism" Tripal Content Type.';
-        throw new Exception($msg);
-      }
-    }
-    if ($report_progress) {
-      $job->setProgress(74);
-    }
-
-    // Create the 'Analysis' entity type. This uses the local:analysis term.
-    drush_print("Creating Analysis...");
-    $args = array(
-      'vocabulary' => 'operation',
-      'accession' => '2945',
-      'term_name' => 'Analysis',
-      'storage_args' => array(
-        'data_table' => 'analysis',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'operation', 'accession' => '2945'));
-    if ($term) {
-      $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered creating "Analysis" Tripal Content Type.';
-        throw new Exception($msg);
-      }
-    }
     if ($report_progress) {
-      $job->setProgress(78);
+      $job->setProgress(85);
     }
+    tripal_chado_prepare_general_types($job);
+    tripal_chado_prepare_genomic_types($job);
+    tripal_chado_prepare_genetic_types($job);
+    tripal_chado_prepare_germplasm_types($job);
+    tripal_chado_prepare_expression_types($job);
+    
+    // Add the supported loaders
+    variable_set('tripal_pub_supported_dbs', array('PMID', 'AGL'));
 
-    // Create the 'Project' entity type. This uses the local:project term.
-    drush_print("Creating Project...");
-    $args = array(
-      'vocabulary' => 'local',
-      'accession' => 'project',
-      'term_name' => 'project',
-      'storage_args' => array(
-        'data_table' => 'project',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'local', 'accession' => 'project'));
-    if ($term) {
-      $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered creating "Project" Tripal Content Type.';
-        throw new Exception($msg);
-      }
-    }
+    // Set a variable to indicate the site is prepared.
+    variable_set('tripal_chado_is_prepared', TRUE);
+    
     if ($report_progress) {
-      $job->setProgress(82);
-    }
+      $job->setProgress(100);
+    }  
+  }
+  catch (Exception $e) {
+    $job->logMessage($e);
+    throw new Exception($e);
+  }
+  
+  // Clear the Drupal menu cache so that the new content types have "add" links.
+  menu_cache_clear_all();
+}
 
-    // Create the 'Map' entity type. This uses the local:project term.
-    drush_print("Creating Map...");
-    $args = array(
-      'vocabulary' => 'data',
-      'accession' => '1274',
-      'term_name' => 'Map',
-      'storage_args' => array(
-        'data_table' => 'featuremap',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'data', 'accession' => '1274'));
-    if ($term) {
-      $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered creating "Map" Tripal Content Type.';
-        throw new Exception($msg);
-      }
-    }
-    // Add cvterm mapping for the Map entity type
-    $identifier = array(
-      'cv_id' => array('name' => 'EDAM'),
-      'name' => 'Map'
-    );
-    $cvterm = chado_get_cvterm($identifier);
-    tripal_chado_add_cvterm_mapping($cvterm->cvterm_id, 'featuremap', NULL);
-    if ($report_progress) {
-      $job->setProgress(86);
-    }
+/**
+ * Creates the "General" category of content types.
+ */
+function tripal_chado_prepare_general_types($job) {
+  
+  //
+  // Create the 'Organism' entity type. This uses the obi:organism term.
+  //  
+  $args = array(
+    'vocabulary' => 'OBI',
+    'accession' => '0100026',
+    'term_name' => 'organism',
+    'storage_args' => array(
+      'data_table' => 'organism',
+    ),
+    'category' => 'General'
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Analysis' entity type. This uses the local:analysis term.
+  //  
+  $args = array(
+    'vocabulary' => 'operation',
+    'accession' => '2945',
+    'term_name' => 'Analysis',
+    'storage_args' => array(
+      'data_table' => 'analysis',
+    ),
+    'category' => 'General'
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+
+  //
+  // Create the 'Project' entity type. This uses the local:project term.
+  //  
+  $args = array(
+    'vocabulary' => 'NCIT',
+    'accession' => 'C47885',
+    'term_name' => 'Project',
+    'storage_args' => array(
+      'data_table' => 'project',
+    ),
+    'category' => 'General'
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
 
+  
+  //
+  // Create the 'Study' entity type. This uses the local:project term.
+  //  
+  $args = array(
+    'vocabulary' => 'SIO',
+    'accession' => '001066',
+    'term_name' => 'Study',
+    'storage_args' => array(
+      'data_table' => 'study',
+    ),
+    'category' => 'General'
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Contact' entity type. This uses the local:contact term.
+  //  
+  $args = array(
+    'vocabulary' => 'local',
+    'accession' => 'contact',
+    'term_name' => 'contact',
+    'storage_args' => array(
+      'data_table' => 'contact',
+    ),
+    'category' => 'General'
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+
+  //
+  // Create the 'Publication' entity type.
+  //      
+  $args = array(
+    'vocabulary' => 'TPUB',
+    'accession' => '0000002',
+    'term_name' => 'Publication',
+    'storage_args' => array(
+      'data_table' => 'pub',
+    ),
+    'category' => 'General'
+  );
+  $bundle = tripal_load_bundle_entity(['accession' => $args['vocabulary'] . ':' . $args['accession']]);
+  if (!$bundle) {
     // Import a publication so we get all of the properties before
     // creating the content type.
     chado_import_pub_by_dbxref('PMID:24163125');
-
-    // Create the 'Publication' entity type.
-    drush_print("Creating Publication...");
-    $error = '';
-    $args = array(
-      'vocabulary' => 'TPUB',
-      'accession' => '0000002',
-      'term_name' => 'Publication',
-      'storage_args' => array(
-        'data_table' => 'pub',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'TPUB', 'accession' => '0000002'));
-    if ($term) {
-        $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered creating "Publication" Tripal Content Type.';
-        throw new Exception($msg);
-      }
-    }
-    // Add cvterm mapping for the Publication entity type
-    $identifier = array(
-      'cv_id' => array('name' => 'tripal_pub'),
-      'name' => 'Publication'
-    );
-    $cvterm = chado_get_cvterm($identifier);
-    tripal_chado_add_cvterm_mapping($cvterm->cvterm_id, 'pub', NULL);
-
+    
+    _tripal_chado_preapre_create_bundle($args, $job);
+    
     // Now remove the publication that was added above.
     $values = array(
       'dbxref_id' => array(
@@ -414,117 +401,388 @@ function tripal_chado_prepare_chado($job = NULL) {
     );
     $result = chado_select_record('pub_dbxref', array('pub_id'), $values);
     chado_delete_record('pub', array('pub_id' => $result[0]->pub_id));
-    if ($report_progress) {
-      $job->setProgress(90);
-    }
+  }
+  
+  //
+  // Create the 'Protocol' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'sep',
+    'accession' => '00101',
+    'term_name' => 'Protocol',
+    'storage_args' => array(
+      'data_table' => 'protocol',
+    ),
+    'category' => 'General'
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+}
 
-    // Create the 'Gene' entity type.
-    drush_print("Creating Gene...");
-    $args = array(
-      'vocabulary' => 'SO',
-      'accession' => '0000704',
-      'term_name' => 'gene',
-      'storage_args' => array(
-        'data_table' => 'feature',
-        'type_column' => 'type_id',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'SO', 'accession' => '0000704'));
-    if ($term) {
-      $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered creating "Gene" Tripal Content Type.';
-        throw new Exception($msg);
-      }
-    }
-    if ($report_progress) {
-      $job->setProgress(94);
-    }
+/**
+ * Creates the "Genomic" category of content types.
+ */
+function tripal_chado_prepare_genomic_types($job) {
+  //
+  // Create the 'Gene' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'SO',
+    'accession' => '0000704',
+    'term_name' => 'gene',
+    'storage_args' => array(
+      'data_table' => 'feature',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Genomic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'mRNA' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'SO',
+    'accession' => '0000234',
+    'term_name' => 'mRNA',
+    'storage_args' => array(
+      'data_table' => 'feature',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Genomic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Phylogenetic tree' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'data',
+    'accession' => '0872',
+    'term_name' => 'Phylogenetic tree',
+    'storage_args' => array(
+      'data_table' => 'phylotree',
+    ),
+    'category' => 'Genomic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  // Create the 'Physical Map' entity type.  
+  $cvterm = tripal_get_cvterm(['id' => 'rdfs:type']);
+  $args = array(
+    'vocabulary' => 'data',
+    'accession' => '1280',
+    'term_name' => 'Physical Map',
+    'storage_args' => array(
+      'data_table' => 'featuremap',
+      'type_linker_table' => 'featuremapprop',
+      'type_column' => 'type_id',
+      'type_id' => $cvterm->cvterm_id,
+      'type_value' => 'physical'
+    ),
+    'category' => 'Genomic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  // Create the 'DNA Library' entity type.  
+  $args = array(
+    'vocabulary' => 'NCIT',
+    'accession' => 'C16223',
+    'term_name' => 'DNA Library',
+    'storage_args' => array(
+      'data_table' => 'library',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Genomic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  // Create the 'Genome Assembly' entity type.  
+  $cvterm = tripal_get_cvterm(['id' => 'rdfs:type']);
+  $args = array(
+    'vocabulary' => 'operation',
+    'accession' => '0525',
+    'term_name' => 'Genome Assembly',
+    'storage_args' => array(
+      'data_table' => 'analysis',
+      'type_linker_table' => 'analysisprop',
+      'type_column' => 'type_id',
+      'type_id' => $cvterm->cvterm_id,
+      'type_value' => 'genome_assembly'
+    ),
+    'category' => 'Genomic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  // Create the 'Genome Annotation' entity type.  
+  $cvterm = tripal_get_cvterm(['id' => 'rdfs:type']);
+  $args = array(
+    'vocabulary' => 'operation',
+    'accession' => '0362',
+    'term_name' => 'Genome Annotation',
+    'storage_args' => array(
+      'data_table' => 'analysis',
+      'type_linker_table' => 'analysisprop',
+      'type_column' => 'type_id',
+      'type_id' => $cvterm->cvterm_id,
+      'type_value' => 'genome_annotation'
+    ),
+    'category' => 'Genomic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  // Create the 'Genome Annotation' entity type.  
+  $cvterm = tripal_get_cvterm(['id' => 'rdfs:type']);
+  $args = array(
+    'vocabulary' => 'local',
+    'accession' => 'Genome Project',
+    'term_name' => 'Genome Project',
+    'storage_args' => array(
+      'data_table' => 'project',
+      'type_linker_table' => 'projectprop',
+      'type_column' => 'type_id',
+      'type_id' => $cvterm->cvterm_id,
+      'type_value' => 'genome_project'
+    ),
+    'category' => 'Genomic',
+  );
+  $bundle = tripal_load_bundle_entity(['accession' => $args['vocabulary'] . ':' . $args['accession']]);
+  _tripal_chado_preapre_create_bundle($args, $job);
+}
 
-    // Create the 'mRNA' entity type.
-    drush_print("Creating mRNA...");
-    $args = array(
-      'vocabulary' => 'SO',
-      'accession' => '0000234',
-      'term_name' => 'mRNA',
-      'storage_args' => array(
-        'data_table' => 'feature',
-        'type_column' => 'type_id',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'SO', 'accession' => '0000234'));
-    if ($term) {
-      $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered  creating "mRNA" Tripal Content Type.';
-        throw new Exception($msg);
-      }
-    }
-    if ($report_progress) {
-      $job->setProgress(98);
-    }
+/**
+ * Creates the "Expression" category of content types.
+ */
+function tripal_chado_prepare_expression_types($job) {
+  //
+  // Create the 'biological sample' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'sep',
+    'accession' => '00195',
+    'term_name' => 'biological sample',
+    'storage_args' => array(
+      'data_table' => 'biomaterial',
+    ),
+    'Expression',
+  );
+  $bundle = tripal_load_bundle_entity(['accession' => $args['vocabulary'] . ':' . $args['accession']]);
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Assay' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'OBI',
+    'accession' => '0000070',
+    'term_name' => 'Assay',
+    'storage_args' => array(
+      'data_table' => 'assay',
+    ),
+    'Expression',
+  );
+  $bundle = tripal_load_bundle_entity(['accession' => $args['vocabulary'] . ':' . $args['accession']]);
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Array Design' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'EFO',
+    'accession' => '0000269',
+    'term_name' => 'Assay Design',
+    'storage_args' => array(
+      'data_table' => 'arraydesign',
+    ),
+    'Expression',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+}
 
-    // Create the 'biological sample' entity type.
-    drush_print("Creating Biological Sample...");
-    $args = array(
-      'vocabulary' => 'sep',
-      'accession' => '00195',
-      'term_name' => 'biological sample',
-      'storage_args' => array(
-        'data_table' => 'biomaterial',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'sep', 'accession' => '00195'));
-    if ($term) {
-        $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered creating "Biological Sample" Tripal Content Type.';
-        throw new Exception($msg);
-      }
-    }
-    if ($report_progress) {
-      $job->setProgress(99);
-    }
+/**
+ * Creates the "Germplasm/Breeding" category of content types.
+ */
+function tripal_chado_prepare_germplasm_types($job) {
+  
+  //
+  // Create the 'Phenotypic Trait' entity type.
+  // 
+  /**
+   * SPF:  We need a bit more testing before we add this conteont type as 
+   * it resolves to the cvterm table. Currently, it can't be created.
+  $args = array(
+    'vocabulary' => 'NCIT',
+    'accession' => 'C85496',
+    'term_name' => 'Phenotypic Trait',
+    'storage_args' => array(
+      'data_table' => 'cvterm',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Germplasm/Breeding',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  */
+  
+  //
+  // Create the 'Germplasm Accession' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'CO_010',
+    'accession' => '0000044',
+    'term_name' => 'Germplasm Accession',
+    'storage_args' => array(
+      'data_table' => 'stock',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Germplasm/Breeding',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Breeding Cross' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'CO_010',
+    'accession' => '0000255',
+    'term_name' => 'Generated germplasm (breeding cross)',
+    'storage_args' => array(
+      'data_table' => 'stock',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Germplasm/Breeding',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Germplasm Variety' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'CO_010',
+    'accession' => '0000029',
+    'term_name' => 'Cultivar (germplasm variety)',
+    'storage_args' => array(
+      'data_table' => 'stock',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Germplasm/Breeding',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Germplasm Variety' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'CO_010',
+    'accession' => '0000162',
+    'term_name' => 'Recombinant Inbred Line',
+    'storage_args' => array(
+      'data_table' => 'stock',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Germplasm/Breeding',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+}
 
-    // Create the 'Phylogenetic tree' entity type.
-    drush_print("Creating Phylogenetic tree...");
-    $args = array(
-      'vocabulary' => 'data',
-      'accession' => '0872',
-      'term_name' => 'Phylogenetic tree',
-      'storage_args' => array(
-        'data_table' => 'phylotree',
-      )
-    );
-    $term = tripal_load_term_entity(array('vocabulary' => 'data', 'accession' => '0872'));
-    if ($term) {
-      $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-    if (!$term or !$bundle) {
-      if (!tripal_create_bundle($args)) {
-        $msg = 'Error Encountered creating "Phylogenetic tree" Tripal Content Type';
-        throw new Exception($msg);
-      }
-    }
-    if ($report_progress) {
-      $job->setProgress(99);
+/**
+ * Creates the "Genetic" category of content types.
+ */
+function tripal_chado_prepare_genetic_types($job) {
+  
+  //
+  // Create the 'Genetic Map' entity type.
+  //  
+  $cvterm = tripal_get_cvterm(['id' => 'rdfs:type']);
+  $args = array(
+    'vocabulary' => 'data',
+    'accession' => '1278',
+    'term_name' => 'Genetic Map',
+    'storage_args' => array(
+      'data_table' => 'featuremap',
+      'type_linker_table' => 'featuremapprop',
+      'type_column' => 'type_id',
+      'type_id' => $cvterm->cvterm_id,
+      'type_value' => 'genetic'
+    ),
+    'category' => 'Genetic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'QTL' entity type. 
+  //  
+  $args = array(
+    'vocabulary' => 'SO',
+    'accession' => '0000771',
+    'term_name' => 'QTL',
+    'storage_args' => array(
+      'data_table' => 'feature',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Genetic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Sequence Variant' entity type.
+  //  
+  $args = array(
+    'vocabulary' => 'SO',
+    'accession' => '0001060',
+    'term_name' => 'Sequence Variant',
+    'storage_args' => array(
+      'data_table' => 'feature',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Genetic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  //
+  // Create the 'Genetic Marker' entity type.
+  //
+  $args = array(
+    'vocabulary' => 'SO',
+    'accession' => '0001645',
+    'term_name' => 'Genetic Marker',
+    'storage_args' => array(
+      'data_table' => 'feature',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Genetic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+  
+  
+  //
+  // Create the 'Heritable Phenotypic Marker' entity type.
+  //
+  $args = array(
+    'vocabulary' => 'SO',
+    'accession' => '0001500',
+    'term_name' => 'Heritable Phenotypic Marker',
+    'storage_args' => array(
+      'data_table' => 'feature',
+      'type_column' => 'type_id',
+    ),
+    'category' => 'Genetic',
+  );
+  _tripal_chado_preapre_create_bundle($args, $job);
+}
+/**
+ * A helper function to consolidate the  code used to create a bundle.
+ */
+function _tripal_chado_preapre_create_bundle($args, $job) {
+  
+  $bundle = tripal_load_bundle_entity(['accession' => $args['vocabulary'] . ':' . $args['accession']]);
+  if (!$bundle) {
+    drush_print("Creating " . $args['term_name'] . "...");
+    if (!tripal_create_bundle($args, $job)) {      
+      $msg = t('Error encountered creating !type Content Type.', ['!type' => $args['term_name']]);
+      throw new Exception($msg);
     }
-
-    // Add the supported loaders
-    variable_set('tripal_pub_supported_dbs', array('PMID', 'AGL'));
-
-    // Set a variable to indicate the site is prepared.
-    variable_set('tripal_chado_is_prepared', TRUE);
   }
-  catch (Exception $e) {
-    $job->logMessage($e);
-    throw new Exception($e);
+  else {
+    drush_print("Content type already created (skipping): " . $args['term_name'] . "...");
   }
 }
 

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

@@ -2824,6 +2824,9 @@ function tripal_chado_bundle_get_properties($table_name, $prop_table, $type_tabl
     $args[':cvterm_id'] = $cvterm_id;
     $props = chado_query($sql, $args);
   }
+  if (!$props) {
+    return [];
+  }
   
   // Iterate through all of the properties and do some final checks to see
   // which ones should be added.

+ 8 - 1
tripal_chado/includes/tripal_chado.mapping.inc

@@ -87,11 +87,18 @@ function tripal_chado_map_cvterms() {
   print "\nDone.\n";
 }
 
-/*
+/**
  * Add a cvterm mapping record
  *
  * Check if the cvterm mapping record exists. If not, add it to the chado_cvterm_mapping
  * table
+ * 
+ * @param $cvterm_id
+ *   The cvterm_id to map.
+ * @param $tablename
+ *   The name of the table that the term maps to.
+ * @param $chado_field
+ *   The field that the term maps to.
  */
 function tripal_chado_add_cvterm_mapping($cvterm_id, $tablename, $chado_field) {
   // check if the record exists

+ 142 - 26
tripal_chado/includes/tripal_chado.semweb.inc

@@ -19,6 +19,7 @@ function tripal_chado_populate_chado_semweb_table() {
   // inserted.
 
   // Now set defaults!
+  tripal_chado_populate_vocab_CO_010();
   tripal_chado_populate_vocab_DC();
   tripal_chado_populate_vocab_EDAM();
   tripal_chado_populate_vocab_ERO();
@@ -390,6 +391,15 @@ function tripal_chado_populate_vocab_SIO() {
     'definition' => 'A cell line is a collection of genetically identifical cells.',
   ));
   chado_associate_semweb_term(NULL, 'cell_line_id', $term);
+  
+  $term = chado_insert_cvterm(array(
+    'id' => 'SIO:001066',
+    'name' => 'study',
+    'cv_name' => 'SIO',
+    'definition' => 'A study is a process that realizes the steps of a study design.',
+  ));
+  chado_associate_semweb_term(NULL, 'study_id', $term);
+  
 }
 
 /**
@@ -408,6 +418,47 @@ function tripal_chado_populate_vocab_SO() {
   chado_associate_semweb_term(NULL, 'feature_id', $term);
 }
 
+
+/**
+ * Adds the Crop Ontology terms.
+ */
+function tripal_chado_populate_vocab_CO_010 () {
+  chado_insert_db(array(
+    'name' => 'CO_010',
+    'description' => 'Crop Germplasm Ontology',
+    'url' => 'http://www.cropontology.org/get-ontology/CO_010',
+    'urlprefix' => 'http://www.cropontology.org/terms/CO_010:{accession}',
+  ));
+  chado_insert_cv(
+    'germplasm_ontology',
+    'GCP germplasm ontology'
+  );
+  $term = chado_insert_cvterm(array(
+    'id' => 'CO_010:0000044',
+    'name' => 'accession',
+    'cv_name' => 'germplasm_ontology',
+    'definition' => '',
+  ));
+  $term = chado_insert_cvterm(array(
+    'id' => 'CO_010:0000255',
+    'name' => 'generated germplasm',
+    'cv_name' => 'germplasm_ontology',
+    'definition' => '',
+  ));
+  $term = chado_insert_cvterm(array(
+    'id' => 'CO_010:0000029',
+    'name' => 'cultivar',
+    'cv_name' => 'germplasm_ontology',
+    'definition' => '',
+  ));
+  $term = chado_insert_cvterm(array(
+    'id' => 'CO_010:0000162',
+    'name' => '414 inbred line',
+    'cv_name' => 'germplasm_ontology',
+    'definition' => '',
+  ));
+}
+
 /**
  * Adds the DC database.
  */
@@ -654,6 +705,20 @@ function tripal_chado_populate_vocab_EDAM() {
     'cv_name' => 'EDAM',
     'definition' => 'Visualise, format or render a molecular sequence or sequences such as a sequence alignment, possibly with sequence features or properties shown.',
   ));
+  
+  $term = chado_insert_cvterm(array(
+    'id' => 'operation:0525',
+    'name' => 'genome assembly',
+    'cv_name' => 'EDAM',
+    'definition' => '',
+  ));
+  
+  $term = chado_insert_cvterm(array(
+    'id' => 'operation:0362',
+    'name' => 'Genome annotation ',
+    'cv_name' => 'EDAM',
+    'definition' => '',
+  ));
 
 }
 /**
@@ -708,6 +773,13 @@ function tripal_chado_populate_vocab_EFO() {
     'definition' => '',
   ));
   chado_associate_semweb_term('arraydesign', 'manufacturer_id', $term);
+  
+  $term = chado_insert_cvterm(array(
+    'id' => 'EFO:0000269',
+    'name' => 'assay design',
+    'cv_name' => 'efo',
+    'definition' => 'An instrument design which describes the design of the array.',
+  ));
 }
 /**
  * Adds the Eagle-i Resource Ontology database and terms.
@@ -738,7 +810,6 @@ function tripal_chado_populate_vocab_ERO() {
     'definition' => 'A technique that samples real world physical conditions and conversion of the resulting samples into digital numeric values that can be manipulated by a computer.',
   ));
   chado_associate_semweb_term(NULL, 'acquisition_id', $term);
-  
 }
 
 /**
@@ -787,6 +858,13 @@ function tripal_chado_populate_vocab_OBI() {
   ));
   chado_associate_semweb_term(NULL, 'organism_id', $term);
   chado_associate_semweb_term('biomaterial', 'taxon_id', $term);
+  
+  $term = chado_insert_cvterm(array(
+    'id' => 'OBI:0000070',
+    'name' => 'assay',
+    'cv_name' => 'obi',
+    'definition' => 'A planned process with the objective to produce information about the material entity that is the evaluant, by physically examining it or its proxies.',
+  ));  
 }
 
 /**
@@ -897,6 +975,10 @@ function tripal_chado_populate_vocab_LOCAL() {
     'organism_property',
     'A local vocabulary that contains locally defined properties for organisms'
   );
+  chado_insert_cv(
+    'analysis_property',
+    'A local vocabulary that contains locally defined properties for analyses'
+  );
   chado_insert_cv(
     'tripal_phylogeny',
     'Terms used by the Tripal phylotree module for phylogenetic and taxonomic trees.'
@@ -965,7 +1047,12 @@ function tripal_chado_populate_vocab_LOCAL() {
   // Add the cv for project properties
   chado_insert_cv(
     'project_property',
-    'A local vocabulary that contains properties for projects'
+    'A local vocabulary that contains properties for projects.'
+  );
+  // Add the cv for project properties
+  chado_insert_cv(
+    'study_property',
+    'A local vocabulary that contains properties for studies.'
   );
   // Add cv for relationship types
   chado_insert_cv(
@@ -1245,7 +1332,7 @@ function tripal_chado_populate_vocab_LOCAL() {
 
   //--------------
   // Project Terms
-  //--------------
+  //-------------- 
   // Insert cvterm 'Project Description' into cvterm table of chado
   // database. This CV term is used to keep track of the project
   // description in the projectprop table.
@@ -1255,6 +1342,13 @@ function tripal_chado_populate_vocab_LOCAL() {
     'cv_name' => 'project_property',
     'db_name' => 'local'
   ));
+  
+  chado_insert_cvterm(array(
+    'name' => 'Project Type',
+    'definition'  => 'A type of project',
+    'cv_name' => 'project_property',
+    'db_name' => 'local'
+  ));
 
   //--------------
   // Natural Diversity Terms
@@ -1529,6 +1623,7 @@ function tripal_chado_populate_vocab_LOCAL() {
   // the 'analysis_property' vocabulary is for user definable properties wo we
   // will add an 'Analysis Type' to this vocubulary
   $term = chado_insert_cvterm(array(
+    'id' => 'local:Analysis Type',
     'name' => 'Analysis Type',
     'definition' => 'The type of analysis that was performed.',
     'cv_name' => 'analysis_property',
@@ -1545,19 +1640,7 @@ function tripal_chado_populate_vocab_LOCAL() {
     '(Random House Kernerman Webster\'s College Dictionary, © 2010 K ' .
     'Dictionaries Ltd).',
     'cv_name' => 'local',
-  ));
-
-  // TODO: change this to foaf:Project
-  $term = chado_insert_cvterm(array(
-    'id' => 'local:project',
-    'name' => 'project',
-    'definition' => 'A plan or proposal for accomplishing something. ' .
-    '(American Heritage® Dictionary of the English Language, Fifth Edition. ' .
-    'Copyright © 2011 by Houghton Mifflin Harcourt Publishing Company).',
-    'cv_name' => 'local',
-  ));
-  chado_associate_semweb_term(NULL, 'project_id', $term);
-  
+  )); 
 
   $term = chado_insert_cvterm(array(
     'id' => 'local:source_data',
@@ -1664,6 +1747,25 @@ function tripal_chado_populate_vocab_LOCAL() {
     'cv_name' => 'local',
   ));
   chado_associate_semweb_term('arraydesign', 'num_sub_rows', $term);
+  
+  
+  //
+  // Terms for Study
+  //
+  chado_insert_cvterm(array(
+    'name' => 'Study Type',
+    'definition'  => 'A type of study',
+    'cv_name' => 'study_property',
+    'db_name' => 'local'
+  ));
+  
+  $term = chado_insert_cvterm(array(
+    'id' => 'local:Genome Project',
+    'name' => 'Genome Project',
+    'definition' => 'A project for whole genome analysis that can include assembly and annotation.',
+    'cv_name' => 'local',
+  ));
+  
 }
 /**
  * Adds the Systems Biology Ontology database and terms.
@@ -1974,15 +2076,7 @@ function tripal_chado_populate_vocab_NCIT() {
     'definition' => 'A term that refers to any individual item or entity in a hierarchy or pedigree. [ NCI ]',
   ));
   chado_associate_semweb_term(NULL, 'phylonode_id', $term);
-    
-  $term = chado_insert_cvterm(array(
-    'id' => 'NCIT:C63536',
-    'name' => 'Study',
-    'cv_name' => 'ncit',
-    'definition' => 'A detailed examination, analysis, or critical inspection of a subject designed to discover facts about it. [ NCI ]',
-  ));
-  chado_associate_semweb_term(NULL, 'study_id', $term);
-  
+     
   $term = chado_insert_cvterm(array(
     'id' => 'NCIT:C15320',
     'name' => 'Study Design',
@@ -1999,7 +2093,29 @@ function tripal_chado_populate_vocab_NCIT() {
     'id' => 'NCIT:C54131',
     'name' => 'Company',
     'cv_name' => 'ncit',
-    'definition' => 'Any formal business entity for profit, which may be a corporation, a partnership, association or individual proprietorship. [ NCI http://dictionary.law.com ]',
+    'definition' => 'Any formal business entity for profit, which may be a corporation, a partnership, association or individual proprietorship.',
+  ));
+  
+  $term = chado_insert_cvterm(array(
+    'id' => 'NCIT:C47885',
+    'name' => 'Project',
+    'cv_name' => 'ncit',
+    'definition' => 'Any specifically defined piece of work that is undertaken or attempted to meet a single requirement.',
+  ));
+  chado_associate_semweb_term(NULL, 'project_id', $term);
+  
+  $term = chado_insert_cvterm(array(
+    'id' => 'NCIT:C16223',
+    'name' => 'DNA Library',
+    'cv_name' => 'ncit',
+    'definition' => 'A collection of DNA molecules that have been cloned in vectors.',
+  ));
+    
+  $term = chado_insert_cvterm(array(
+    'id' => 'NCIT:C85496',
+    'name' => 'Trait',
+    'cv_name' => 'ncit',
+    'definition' => 'Any genetically determined characteristic.',
   ));
   
   $term = chado_insert_cvterm(array(

+ 89 - 1
tripal_chado/tripal_chado.install

@@ -30,6 +30,8 @@ function tripal_chado_install() {
     ";
     chado_query($sql);
   }
+  
+  tripal_insert_variable('bundle_category', 'Bundles can be categorized to allow for grouping');
 }
 
 /**
@@ -1600,7 +1602,93 @@ function tripal_chado_update_7329() {
   }
 }
 
-# tripal_chado_update_7330 is in PR #596 and adds categories for content types.
+/**
+ * Associates categories with content types.
+ */
+function tripal_chado_update_7330() {
+  try {
+    tripal_insert_variable('bundle_category', 'Bundles can be categorized to allow for grouping');
+    
+    $bundles = [
+      'General' => [
+        // Organism
+        'OBI:0100026',
+        // Analyis
+        'operation:2945',
+        // Project
+        'NCIT:C47885',
+        // Study
+        'SIO:001066',
+        // Contact
+        'local:contact',
+        // Publication
+        'TPUB:0000002',
+        // Protocol
+        'sep:00101',        
+      ],
+      'Genomic' => [
+        // Gene
+        'SO:0000704',
+        // mRNA
+        'SO:0000234',
+        // Phylogenetci Tree
+        'data:0872',
+        // Physical Map
+        'data:1280',
+        // DNA Library
+        'NCIT:C16223',
+        // Genome Assembly
+        'operation:0525',
+        // Genome Annotation
+        'operation:0362',
+        // Genome Project
+        'local:Genome Project',                
+      ],
+      'Genetic' => [
+        // Genetic Map
+        'data:1278',
+        // QTL
+        'SO:0000771',
+        // Sequence Variant
+        'SO:0001060',
+        // Genetic Marker
+        'SO:0001645',
+        // Heritable Phenotypic Marker
+        'SO:0001500',        
+      ],
+      'Germplasm/Breeding' => [
+        // Germplasm Accession
+        'CO_010:0000044',
+        // Breeding Cross
+        'CO_010:0000255',
+        // Cutlivar
+        'CO_010:0000029',
+        // Recombinant Inbred Line
+        'CO_010:0000162',        
+      ],
+      'Expression' => [
+        // Biological Sample
+        'sep:00195',
+        // Assay
+        'OBI:0000070',
+        // Array Design 
+        'EFO:0000269',
+      ]
+    ];
+    foreach ($bundles as $category => $accessions) {
+      foreach ($accessions as $accession) {
+        $bundle = tripal_load_bundle_entity(['accession' => $accession]);
+        if ($bundle) {
+          tripal_set_bundle_variable('bundle_category', $bundle->id, $category);
+        }
+      }      
+    }    
+  }
+  catch (\PDOException $e) {
+    $error = $e->getMessage();
+    throw new DrupalUpdateException('Could not perform update: '. $error);
+  }
+}
 
 /**
  * Adds a base_type_id to the chado_bundle table.