Browse Source

Merge branch '7.x-2.x' into entities

Stephen Ficklin 9 years ago
parent
commit
d175afd4d2

+ 14 - 37
README.txt

@@ -2,22 +2,23 @@ What is Tripal?
 --------------
 Tripal is a collection of open-source freely available Drupal modules 
 and is a member of the GMOD family of tools. Tripal serves as a web 
-interface for the GMOD Chado database and is designed to allow anyone 
-with genomic data to quickly create an online genomic database using 
-community supported tools.
+interface for the GMOD Chado database and is designed to reduce the
+time and cost required for construction of an online genomic, genetic
+and breeding database.
 
 
 Features
 --------------
  - a Chado installer
  - Data loaders for ontologies (controlled vocabularies), GFF files, 
-   and FASTA files
- - Generic Data Loader Modules allows for creation of custom loading 
-   templates
+   and FASTA files, publications (from PubMed and AGIRCOLA). 
+ - Generic Bulk Data Loader Modules allows for creation of custom 
+   loading templates.
  - Drupal nodes (web pages) are automatically generated for organisms,
    genomic features, biological libraries, and stocks
- - Web pages can be enriched with analysis results from BLAST, 
-   KAAS/KEGG, InterProScan, and Gene Ontology (GO)
+ - Supports creation of materialized views for faster data queries.
+ - Display templates are provided for all content types for
+   easier customization.
  - Views Integration allows for custom listings of data
  - Content pieces exposed as blocks allowing the use of Panels for 
    custom layouts of Tripal Nodes
@@ -25,24 +26,18 @@ Features
 
 Required Modules
 --------------
- - Drupal 6.x (work is currently underway for a 7.x compatible 
-   version)
- - Drupal Core Modules: Search and Path
+ - Drupal 7.x 
+ - Drupal Core Modules: Search, Path and PHP modules.
+ - Drupal contributed modules: Views
  - Database containing GMOD Chado Schema (can be installed by the 
    Tripal Core module)
 NOTE: A PostgreSQL database is required for installation of the 
 Chado Schema
 
-Highly Recommended Modules
- - Views 2.x (Views 3.x compatible version already exists in 6.x-0.4-dev)
- - Views Data Export
-
-
 Installation
 --------------
-Please follow the online tutorial for installation instructions:
-http://www.gmod.org/wiki/Tripal_Tutorial_v1.1
-
+Please follow the instructions in the online Tripal User's Guide:
+http://tripal.info/tutorials/v2.0/installation
 
 Customization
 --------------
@@ -51,21 +46,3 @@ PHP-based template files are provided for all data types to allow for
 precise customizations as required by the community. A well-developed 
 Tripal API provides a uniform set of variables and functions for 
 accessing any and all data within the Chado database.
-
-
-Future Work
---------------
-Currently, Tripal only supports a large subset of the 
-current Chado schema, but further development is underway. Meanwhile, 
-others can use the Tripal API to develop their own extensions. Those 
-extensions can in turn be made available for anyone to use. These 
-custom extensions, the Tripal package, and access to support resource 
-such as an active mailing list can be found on the Tripal website 
-(http://tripal.sourceforge.net).
-
-For more information, see the recent publication:
-
-Stephen P. Ficklin, Lacey-Anne Sanderson, Chun-Huai Cheng, Margaret 
-Staton, Taein Lee, Il-Hyung Cho, Sook Jung, Kirstin E Bett, Dorrie 
-Main. Tripal: a construction Toolkit for Online Genome Databases. 
-Database, Sept 2011. Vol 2011. 

+ 3 - 3
tripal_analysis/includes/tripal_analysis.delete.inc

@@ -88,7 +88,7 @@ function tripal_analysis_delete_analyses($analyses, $job = NULL) {
   // function which is not prefix with the schema, and an error occurs.
   // Therefore, we set the active database to chado to get around that
   // problem.
-  $previous_db = chado_set_active('chado');
+//  $previous_db = chado_set_active('chado');
 
   // begin the transaction
   $transaction = db_transaction();
@@ -98,7 +98,7 @@ function tripal_analysis_delete_analyses($analyses, $job = NULL) {
 
   try {
     $values = array(
-        analysis_id => $analyses
+        'analysis_id' => $analyses
     );
     $num_deletes = chado_select_record('analysis', array('count(*) as cnt'), $values);
     print "Deleting " . $num_deletes[0]->cnt . " analyses\n";
@@ -114,6 +114,6 @@ function tripal_analysis_delete_analyses($analyses, $job = NULL) {
     watchdog_exception('tripal_analysis', $e);
     return 0;
   }
-  chado_set_active($previous_db);
+//  chado_set_active($previous_db);
   print "\nDone\n";
 }

+ 2 - 2
tripal_bulk_loader/includes/tripal_bulk_loader.constants.inc

@@ -252,7 +252,7 @@ function tripal_bulk_loader_set_constants_form($form, &$form_state, $node) {
           case 'table field':
             $form['exposed_fields']['new'][$record_id . '-' . $field_id] = array(
               '#type' => 'textfield',
-              '#title' => t('%title', array('%title' => $field['title'])),
+              '#title' => t('@title', array('@title' => $field['title'])),
               '#description' => t('%exposed_description', array('%exposed_description' => $field['exposed_description'])),
               '#default_value' => $default_value,
             );
@@ -260,7 +260,7 @@ function tripal_bulk_loader_set_constants_form($form, &$form_state, $node) {
           case 'constant':
             $form['exposed_fields']['new'][$record_id . '-' . $field_id] = array(
               '#type' => 'textfield',
-              '#title' => t('%title', array('%title' => $field['title']) ),
+              '#title' => t('@title', array('@title' => $field['title']) ),
               '#description' => t('Enter the case-sensitive value of this constant for your data file'),
               '#default_value' => $default_value,
             );

+ 0 - 11
tripal_bulk_loader/theme/templates/tripal_bulk_loader_admin.tpl.php

@@ -1,11 +0,0 @@
-<h3>Module Description:</h3>
-<p>This module allows you to create loading templates for any tab-delimited
-   data file which can be used repetitively for loading data into chado. The Loading Templates are a direct mapping
-   between the columns in your file and the columns in chado tables. To use this tool
-   you need to be very familar with the chado schema -See
-   <?php  l(t('Chado -Getting Started'), 'http://gmod.org/wiki/Chado_-_Getting_Started') ?>.
-   The ability to add constants and specify values via foreign key contraints is also provided
-   in order for the loader to fill chado columns which may be required but are not specified
-   in your input file.
-</p>
-<br />

+ 35 - 0
tripal_bulk_loader/theme/templates/tripal_bulk_loader_help.tpl.php

@@ -0,0 +1,35 @@
+<p>The bulk loader is a tool that Tripal provides for loading of data contained in tab 
+delimited files. Tripal supports loading of files in standard formats (e.g. FASTA, GFF, OBO), 
+but Chado can support a variety of different biological data types and there are often no 
+community standard file formats for loading these data. For example, there is no file 
+format for importing genotype and phenotype data. Those data can be stored in the feature, 
+stock and natural diversity tables of Chado. The Bulk Loader was introduced in Tripal v1.1 
+and provides a web interface for building custom data loader. In short, the site developer 
+creates the bulk loader "template". This template can then be used and re-used for any tab 
+delimited file that follows the format described by the template. Additionally, bulk loading 
+templates can be exported allowing Tripal sites to share loaders with one another.  Loading 
+templates that have been shared are available on the Tripal website here: 
+<?php print l('http://tripal.info/extensions/bulk-loader-templates', 'http://tripal.info/extensions/bulk-loader-templates');?>.</p>
+<br />
+<h3>General Usage</h3>
+<ol>
+<li><strong>Plan how to store your data.</strong>
+  <br />This is the most important and often the most difficult step. This
+  is because it requires familiarity with the Chado database schema and due to the
+  flexibility of the schema, you may be able to store your data multiple ways. It is
+  considered best practice to consult the GMOD website and the Chado community (via the 
+  <?php print l('gmod-schema mailing list', 'https://lists.sourceforge.net/lists/listinfo/gmod-schema');?>) when deciding how to store data.</li>
+<li><strong>Create a new Bulk Loading Template to map the columns from your data file to chado.</strong>
+  <br />Creating a new template can be done by clicking on the "Templates" tab above
+  and then the "Add Template" link. Note that the template is designed with a single line
+  from your file in mind. Furthermore, the term "record" refers to a single entry in chado
+  and the term "field" refers to a column in a specific chado table.</li>
+<li><strong>Create a Bulk Loader Job with file-specific details that uses your template to load a 
+specific file.</strong>
+  <br />Create a Bulk Loading Job by clicking on the "Jobs" tab above and then "Add Bulk 
+  Loading Job". Remember to select the template you just created and to ensure that you
+  provide the absolute path to the file. Note: The file must already be uploaded to the
+  same server as your Drupal installation and must be readable by the command-line
+  user who executes the tripal job.</li>
+</ol>
+<p>For the full tutorial, see the <?php print l('Tripal User Manual: The Bulk Loader', 'http://tripal.info/node/109');?>.</p>

+ 5 - 4
tripal_bulk_loader/tripal_bulk_loader.module

@@ -84,7 +84,8 @@ function tripal_bulk_loader_menu() {
   $items['admin/tripal/loaders/bulk/help'] = array(
     'title' => 'Help',
     'description' => "A description of the Tripal Bulk Loader module including a short description of it's usage.",
-    'page callback' => 'tripal_bulk_loader_admin_manage_templates',
+    'page callback' => 'theme',
+    'page arguments' => array('tripal_bulk_loader_help'),
     'access arguments' => array('administer tripal_bulk_loader'),
     'weight' => 10,
     'type' => MENU_LOCAL_TASK,
@@ -325,9 +326,9 @@ function tripal_bulk_loader_theme($existing, $type, $theme, $path) {
       ),
     ),
 
-    // admin theme
-    'tripal_bulk_loader_admin' => array(
-      'template' => 'tripal_bulk_loader_admin',
+    // help page
+    'tripal_bulk_loader_help' => array(
+      'template' => 'tripal_bulk_loader_help',
       'path' => "$path/theme/templates",
     ),
 

+ 78 - 21
tripal_core/api/tripal_core.chado_general.api.inc

@@ -44,34 +44,91 @@ require_once 'tripal_core.schema_v1.11.api.inc';
  * Set the Tripal Database
  *
  * The chado_set_active function is used to prevent namespace collisions
- * when chado and drupal are installed in the same database but in different
- * schemas.  It is also used for backwards compatibility with older versions
- * of tripal or in cases where chado is located outside of the Drupal database.
- * or when using Drupal functions such as db_table_exists()
+ * when Chado and Drupal are installed in the same database but in different
+ * schemas. It is also used when using Drupal functions such as
+ * db_table_exists().
+ *
+ * The connection settings can be altered through the hook
+ * hook_chado_connection_alter.
+ *
+ * Current active connection name is stored in the global variable
+ * $GLOBALS['chado_active_db'].
+ *
+ * @see hook_chado_connection_alter()
  *
  * @ingroup tripal_chado_api
  */
-function chado_set_active($dbname  = 'default') {
-  global $databases, $active_db;
+function chado_set_active($dbname = 'default') {
 
-  if ($dbname ) {
-    if ($dbname == 'chado') {
-      db_query('set search_path to chado,public');
-      return 'default';
-    }
-    else {
-      db_query('set search_path to public');
-      return 'chado';
-    }
+  // Check if the chado_active_db has been set yet.
+  if (!array_key_exists('chado_active_db', $GLOBALS)) {
+    $GLOBALS['chado_active_db'] = 'default';
   }
-  // if the 'chado' database is in the $db_url variable then chado is
-  // not in the same Drupal database, so we don't need to set any
-  // search_path and can just change the database
-  elseif (array_key_exists($dbname, $databases)) {
-    return db_set_active($dbname);
+
+  $previous_db = $active_db = $GLOBALS['chado_active_db'];
+  $search_path = 'public';
+
+  // Change only if 'chado' has been specified.
+  if ($dbname == 'chado') {
+    $active_db = 'chado';
+    $search_path = 'chado,public';
   }
+
+  $settings = array(
+    'dbname'          => $dbname,
+    'new_active_db'   => &$active_db,
+    'new_search_path' => &$search_path,
+  );
+
+  // Will call all modules implementing hook_chado_search_path_alter
+  // note: hooks can alter $active_db and $search_path.
+  drupal_alter('chado_connection', $settings);
+
+  // set chado_active_db to remember active db
+  $GLOBALS['chado_active_db'] = $active_db;
+
+  // set PostgreSQL search_path
+  db_query('SET search_path TO ' . $search_path);
+
+  return $previous_db;
 }
 
+
+/**
+ * Alter Chado connection settings.
+ *
+ * This hook is useful for multi-chado instances. Tripal core functions
+ * call the chado_set_active() function (e.g. chado_query) but there is no
+ * opportunity elsewhere to set the active database.  This is useful in two
+ * cases:  1) Users are managed at the database level as in the case of
+ * SouthGreen Bioinformatics Platform tools (e.g. Banana Genone Hub).
+ * This allows custom modules to change the database connections on a per-user
+ * basis, and each user permissions is managed at the database level.  Users
+ * are managed at the database level to provid the same access restrictions
+ * across various tools that use Chado (e,g, Artemis) 2) When there are
+ * simply two Chado instances housed in different Chado databases and the
+ * module needs to control which one is being used at any given time.
+ *
+ * @param $settings
+ *   An array containing
+ *
+ * @see chado_set_active()
+ *
+ * @ingroup tripal_chado_api
+ */
+function hook_chado_connection_alter(&$settings) {
+  // This example shows how we could make sure no table of the 'public' schema
+  // would be allowed in the coming queries: to do so, the caller will call
+  // "chado_set_active('chado_only');" and the hook will remove 'public' from
+  // the search path.
+  if ('chado_only' == $settings['dbname']) {
+    $settings['new_active_db']   = 'chado';
+    // We don't include 'public' in search path.
+    $settings['new_search_path'] = 'chado';
+  }
+}
+
+
 /**
  * Get max rank for a given set of criteria
  * This function was developed with the many property tables in chado in mind but will
@@ -708,4 +765,4 @@ function chado_get_record_with_property($record, $property, $options = array())
   }
 
   return $records;
-}
+}

+ 3 - 3
tripal_core/api/tripal_core.tripal.api.inc

@@ -126,7 +126,7 @@ function tripal_report_error($type, $severity, $message, $variables = array(), $
   }
 
   // Print to the Tripal error log
-  tripal_log( $severity_string . ' (' . strtoupper($type) . '): ' . $print_message . "\n", 'error');
+  tripal_log('[' . strtoupper($type) . '] ' . $print_message . "\n", $severity_string);
 
 }
 
@@ -221,14 +221,14 @@ function tripal_set_message($message, $importance = TRIPAL_INFO, $options = arra
  */
 function tripal_log($message, $type = 'error', $options = array()) {
   global $base_url;
-  $prefix = '[TRIPAL ' . strtoupper(check_plain($type)) . '] ';
+  $prefix = '[site ' . $base_url . '] [TRIPAL ' . strtoupper(check_plain($type)) . '] ';
 
   if (!isset($options['is_progress_bar'])) {
     $message = $prefix . str_replace("\n", "", trim($message));
   }
 
   if (isset($options['first_progress_bar'])) {
-    $message = trim($message);
+    $message = $prefix . trim($message);
   }
 
   return error_log($message);

+ 7 - 7
tripal_core/includes/tripal_core.chado_install.inc

@@ -273,11 +273,11 @@ function tripal_core_install_sql($sql_file) {
     // Find SQL for new objects
     if (preg_match('/^\s*CREATE\s+TABLE/i', $line) and !$in_string) {
       $stack[] = 'table';
-      $line = preg_replace("/public./", "chado.", $line);
+      $line = preg_replace("/public\./", "chado.", $line);
     }
     if (preg_match('/^\s*ALTER\s+TABLE/i', $line) and !$in_string) {
       $stack[] = 'alter table';
-      $line = preg_replace("/public./", "chado.", $line);
+      $line = preg_replace("/public\./", "chado.", $line);
     }
     if (preg_match('/^\s*SET/i', $line) and !$in_string) {
       $stack[] = 'set';
@@ -287,26 +287,26 @@ function tripal_core_install_sql($sql_file) {
     }
     if (preg_match('/^\s*CREATE\s+SEQUENCE/i', $line) and !$in_string) {
       $stack[] = 'sequence';
-      $line = preg_replace("/public./", "chado.", $line);
+      $line = preg_replace("/public\./", "chado.", $line);
     }
     if (preg_match('/^\s*CREATE\s+(?:OR\s+REPLACE\s+)*VIEW/i', $line) and !$in_string) {
       $stack[] = 'view';
-      $line = preg_replace("/public./", "chado.", $line);
+      $line = preg_replace("/public\./", "chado.", $line);
     }
     if (preg_match('/^\s*COMMENT/i', $line) and !$in_string and sizeof($stack)==0) {
       $stack[] = 'comment';
-      $line = preg_replace("/public./", "chado.", $line);
+      $line = preg_replace("/public\./", "chado.", $line);
     }
     if (preg_match('/^\s*CREATE\s+(?:OR\s+REPLACE\s+)*FUNCTION/i', $line) and !$in_string) {
       $stack[] = 'function';
-      $line = preg_replace("/public./", "chado.", $line);
+      $line = preg_replace("/public\./", "chado.", $line);
     }
     if (preg_match('/^\s*CREATE\s+INDEX/i', $line) and !$in_string) {
       $stack[] = 'index';
     }
     if (preg_match('/^\s*INSERT\s+INTO/i', $line) and !$in_string) {
       $stack[] = 'insert';
-      $line = preg_replace("/public./", "chado.", $line);
+      $line = preg_replace("/public\./", "chado.", $line);
     }
     if (preg_match('/^\s*CREATE\s+TYPE/i', $line) and !$in_string) {
       $stack[] = 'type';

+ 101 - 0
tripal_cv/files/cv_property.obo

@@ -0,0 +1,101 @@
+format-version: 1.2
+date: 11:09:2010 16:00
+saved-by: scottcain
+default-namespace: cv_property
+remark: Initially generated by Scott Cain, sourced from GO, SO, OBO_REL.
+data-version: 1.0
+
+[Typedef]
+id: CVP:cv_property
+name: cv_property
+namespace: cv_property
+def: "A general purpose relation between an ontology meta tag some value" []
+
+[Typedef]
+id: CVP:data-version
+name: data-version
+namespace: cv_property
+def: "The release version of the ontology" []
+is_a: CVP:cv_property
+range: xsd:float
+
+[Typedef]
+id: CVP:remark
+name: remark
+namespace: cv_property
+def: "A free text comment about the ontology." []
+is_a: CVP:cv_property
+range: xsd:string
+
+[Typedef]
+id: CVP:date
+name: date
+namespace: cv_property
+def: "The creation date for the obo file." []
+is_a: CVP:cv_property
+range: xsd:dateTime
+
+[Typedef]
+id: CVP:subset
+name: subset
+namespace: cv_property
+def: "The 'name' part of the subsetdef string, which can be used to match the subset term in terms." []
+is_a: CVP:cv_property
+range: xsd:string
+
+[Typedef]
+id: CVP:subsetdef
+name: subsetdef
+namespace: cv_property
+def: "Text to define subsets of the ontology.  For format is 'tagname' space 'tag definition'." []
+is_a: CVP:cv_property
+range: xsd:string
+
+[Typedef]
+id: CVP:synonymtypedef
+name: synonymtypedef
+namespace: cv_property
+def: "Information about the synonyms used in the obo file." []
+is_a: CVP:cv_property
+range: xsd:string
+
+[Typedef]
+id: CVP:default-namespace
+name: default-namespace
+namespace: cv_property
+def: "Information about the default name space of the ontology." []
+is_a: CVP:cv_property
+range: xsd:string
+
+[Typedef]
+id: CVP:saved-by
+name: saved-by
+namespace: cv_property
+def: "Information about the person who edited the obo file (not necessarily a real name)."  []
+is_a: CVP:cv_property
+range: xsd:string
+
+[Typedef]
+id: CVP:idspace
+name: idspace
+namespace: cv_property
+def: "UNKNOWN" []
+is_a: CVP:cv_property
+range: xsd:string
+
+[Typedef]
+id: CVP:treat-xrefs-as-equivalent
+name: treat-xrefs-as-equivalent
+namespace: cv_property
+def: "UNKNOWN" []
+is_a: CVP:cv_property
+range: xsd:string
+
+[Typedef]
+id: CVP:ontology
+name: ontology
+namespace: cv_property
+def: "UNKNOWN" []
+is_a: CVP:cv_property
+range: xsd:string
+

+ 234 - 25
tripal_cv/includes/tripal_cv.obo_loader.inc

@@ -33,33 +33,132 @@ function tripal_cv_obo_form($form, &$form_state) {
   $results = db_query($sql);
 
   $obos = array();
-  $obos[] = '';
+  $obos[] = 'Select a Vocabulary';
   foreach ($results as $obo) {
-//    $obos[$obo->obo_id] = "$obo->name  | $obo->path";
     $obos[$obo->obo_id] = $obo->name;
   }
 
-  $form['obo_existing'] = array(
+  $obo_id = '';
+  if (array_key_exists('values', $form_state)) {
+    $obo_id = array_key_exists('obo_id', $form_state['values']) ? $form_state['values']['obo_id'] : '';
+  }
+
+  $form['instructions'] = array(
     '#type' => 'fieldset',
-    '#title' => t('Use a Saved Ontology OBO Reference')
+    '#title' => 'instructions',
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+  $form['instructions']['info'] = array(
+    '#type' => 'item',
+    '#markup' => t('This page allows you to load vocabularies and ontologies
+      that are in OBO format. Once loaded, the terms from these
+      vocabularies can be used to categorize data in the database.
+      You may use the form below to either reload a vocabulary that is already
+      loaded (as when new updates to that vocabulary are available) or load a new
+      vocabulary.'),
   );
 
-  $form['obo_new'] = array(
+  $form['obo_existing'] = array(
     '#type' => 'fieldset',
-    '#title' => t('Use a New Ontology OBO Reference')
+    '#title' => t('Use a Saved Ontology OBO Reference'),
+    '#prefix' => '<span id="obo-existing-fieldset">',
+    '#suffix' => '</span>'
   );
 
   $form['obo_existing']['existing_instructions']= array(
-    '#value' => t('The Ontology OBO files listed in the drop down below have been automatically added upon
-                   installation of the Tripal CV module or were added from a previous upload.  Select
-                   an OBO, then click the submit button to load the vocabulary into the database.  If the
-                   vocabularies already exist then the ontology will be updated.'),
+    '#type' => 'item',
+    '#markup' => t('The vocabularies listed in the select box below have bene pre-populated
+      upon installation of Tripal or have been previously loaded.  Select one to edit
+      its settings or submit for loading.  You may reload any vocabulary that has
+      already been loaded to retrieve any new updates.'),
   );
 
   $form['obo_existing']['obo_id'] = array(
     '#title' => t('Ontology OBO File Reference'),
     '#type' => 'select',
     '#options' => $obos,
+    '#ajax' => array(
+      'callback' => 'tripal_cv_obo_form_ajax_callback',
+      'wrapper' => 'obo-existing-fieldset',
+    ),
+  );
+
+  // If the user has selected an OBO ID then get the form elements for
+  // updating.
+  if ($obo_id) {
+    $uobo_name = '';
+    $uobo_url = '';
+    $uobo_file = '';
+
+    $vocab = db_select('tripal_cv_obo', 't')
+      ->fields('t', array('name', 'path'))
+      ->condition('obo_id', $obo_id)
+      ->execute()
+      ->fetchObject();
+    $uobo_name = $vocab->name;
+    if (preg_match('/^http/', $vocab->path)) {
+      $uobo_url = $vocab->path;
+    }
+    else {
+      $uobo_file = trim($vocab->path);
+      $matches = array();
+      if (preg_match('/\{(.*?)\}/', $uobo_file, $matches)) {
+        $modpath = drupal_get_path('module', $matches[1]);
+        $uobo_file = '/' . preg_replace('/\{.*?\}/', $modpath, $uobo_file);
+      }
+    }
+    // We don't want the previous value to remain. We want the new default to
+    // show up, so remove the input values
+    unset($form_state['input']['uobo_name']);
+    unset($form_state['input']['uobo_url']);
+    unset($form_state['input']['uobo_file']);
+
+    $form['obo_existing']['uobo_name']= array(
+      '#type'          => 'textfield',
+      '#title'         => t('Vocabulary Name'),
+      '#description'   => t('Please provide a name for this vocabulary.  After upload, this name will appear in the drop down
+                           list above for use again later.'),
+      '#default_value'  => $uobo_name,
+    );
+
+    $form['obo_existing']['uobo_url']= array(
+      '#type'          => 'textfield',
+      '#title'         => t('Remote URL'),
+      '#description'   => t('Please enter a URL for the online OBO file.  The file will be downloaded and parsed.
+                           (e.g. http://www.obofoundry.org/ro/ro.obo'),
+      '#default_value' => $uobo_url,
+    );
+
+    $form['obo_existing']['uobo_file']= array(
+      '#type'          => 'textfield',
+      '#title'         => t('Local File'),
+      '#description'   => t('Please enter the file system path for an OBO
+        definition file. If entering a path relative to
+        the Drupal installation you may use a relative path that excludes the
+        Drupal installation directory (e.g. sites/default/files/xyz.obo). Note
+        that Drupal relative paths have no preceeding slash.
+        Otherwise, please provide the full path on the filesystem.  The path
+        must be accessible to the web server on which this Drupal instance is running.'),
+      '#default_value' => $uobo_file,
+    );
+    $form['obo_existing']['update_obo_details']= array(
+      '#type' => 'submit',
+      '#value' => 'Update Ontology Details',
+      '#name' => 'update_obo_details'
+    );
+    $form['obo_existing']['update_load_obo']= array(
+      '#type' => 'submit',
+      '#value' => 'Load Vocabulary',
+      '#name' => 'update_load_obo'
+    );
+  }
+
+  $form['obo_new'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Add a New Ontology OBO Reference'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
   );
 
   $form['obo_new']['path_instructions']= array(
@@ -83,17 +182,21 @@ function tripal_cv_obo_form($form, &$form_state) {
   );
 
   $form['obo_new']['obo_file']= array(
-    '#type'          => 'textfield',
-    '#title'         => t('Local File'),
-    '#description'   => t('Please enter the full system path for an OBO definition file, or a path within the Drupal
-                           installation (e.g. /sites/default/files/xyz.obo).  The path must be accessible to the
-                           server on which this Drupal instance is running.'),
+    '#type'  => 'textfield',
+    '#title'  => t('Local File'),
+    '#description' => t('Please enter the file system path for an OBO
+        definition file. If entering a path relative to
+        the Drupal installation you may use a relative path that excludes the
+        Drupal installation directory (e.g. sites/default/files/xyz.obo). Note
+        that Drupal relative paths have no preceeding slash.
+        Otherwise, please provide the full path on the filesystem.  The path
+        must be accessible to the web server on which this Drupal instance is running.'),
   );
 
-  $form['submit'] = array(
-    '#type'         => 'submit',
-    '#value'        => t('Submit'),
-    '#executes_submit_callback' => TRUE,
+  $form['obo_new']['add_new_obo'] = array(
+    '#type'  => 'submit',
+    '#value' => t('Add this vocabulary'),
+    '#name' => 'add_new_obo',
   );
 
   $form['#redirect'] = 'admin/tripal/tripal_cv/obo_loader';
@@ -101,6 +204,72 @@ function tripal_cv_obo_form($form, &$form_state) {
   return $form;
 }
 
+/**
+ *
+ * @param $form
+ * @param $form_state
+ */
+function tripal_cv_obo_form_validate($form, &$form_state) {
+  $obo_id    = $form_state['values']['obo_id'];
+  $obo_name  = trim($form_state['values']['obo_name']);
+  $obo_url   = trim($form_state['values']['obo_url']);
+  $obo_file  = trim($form_state['values']['obo_file']);
+  $uobo_name  = array_key_exists('uobo_name', $form_state['values']) ? trim($form_state['values']['uobo_name']) : '';
+  $uobo_url   = array_key_exists('uobo_url', $form_state['values']) ? trim($form_state['values']['uobo_url']) : '';
+  $uobo_file  = array_key_exists('uobo_file', $form_state['values']) ? trim($form_state['values']['uobo_file']) : '';
+
+  // Make sure if the name is changed it doesn't conflict with another OBO.
+  if ($form_state['clicked_button']['#name'] == 'update_obo_details' or
+      $form_state['clicked_button']['#name'] == 'update_load_obo') {
+    // Get the current record
+    $vocab = db_select('tripal_cv_obo', 't')
+      ->fields('t', array('obo_id', 'name', 'path'))
+      ->condition('name', $uobo_name)
+      ->execute()
+      ->fetchObject();
+    if ($vocab and $vocab->obo_id != $obo_id) {
+      form_set_error('uobo_name', 'The vocabulary name must be different from existing vocabularies');
+    }
+    // Make sure the file exists. First check if it is a relative path
+    $dfile = $_SERVER['DOCUMENT_ROOT'] . base_path() . $uobo_file;
+    if (!file_exists($dfile)) {
+      if (!file_exists($uobo_file)) {
+        form_set_error('uobo_file', 'The specified path does not exist or cannot be read.');
+      }
+    }
+    if (!$uobo_url and !$uobo_file) {
+      form_set_error('uobo_url', 'Please provide a URL or a path for the vocabulary.');
+    }
+    if ($uobo_url and $uobo_file) {
+      form_set_error('uobo_url', 'Please provide only a URL or a path for the vocabulary, but not both.');
+    }
+  }
+  if ($form_state['clicked_button']['#name'] == 'add_new_obo') {
+    // Get the current record
+    $vocab = db_select('tripal_cv_obo', 't')
+      ->fields('t', array('obo_id', 'name', 'path'))
+      ->condition('name', $obo_name)
+      ->execute()
+      ->fetchObject();
+    if ($vocab) {
+      form_set_error('obo_name', 'The vocabulary name must be different from existing vocabularies');
+    }
+    // Make sure the file exists. First check if it is a relative path
+    $dfile = $_SERVER['DOCUMENT_ROOT'] . base_path() . $obo_file;
+    if (!file_exists($dfile)) {
+      if (!file_exists($obo_file)) {
+        form_set_error('obo_file', 'The specified path does not exist or cannot be read.');
+      }
+    }
+    if (!$obo_url and !$obo_file) {
+      form_set_error('obo_url', 'Please provide a URL or a path for the vocabulary.');
+    }
+    if ($obo_url and $obo_file) {
+      form_set_error('obo_url', 'Please provide only a URL or a path for the vocabulary, but not both.');
+    }
+  }
+}
+
 /**
  * The submit function for the load ontology form. It registers a
  *   tripal job to import the user specified ontology file
@@ -114,17 +283,52 @@ function tripal_cv_obo_form($form, &$form_state) {
  * @ingroup tripal_obo_loader
  */
 function tripal_cv_obo_form_submit($form, &$form_state) {
+
   $obo_id    = $form_state['values']['obo_id'];
   $obo_name  = trim($form_state['values']['obo_name']);
   $obo_url   = trim($form_state['values']['obo_url']);
   $obo_file  = trim($form_state['values']['obo_file']);
+  $uobo_name  = array_key_exists('uobo_name', $form_state['values']) ? trim($form_state['values']['uobo_name']) : '';
+  $uobo_url   = array_key_exists('uobo_url', $form_state['values']) ? trim($form_state['values']['uobo_url']) : '';
+  $uobo_file  = array_key_exists('uobo_file', $form_state['values']) ? trim($form_state['values']['uobo_file']) : '';
+
+  // If the user requested to alter the details then do that.
+  if ($form_state['clicked_button']['#name'] == 'update_obo_details' or
+      $form_state['clicked_button']['#name'] == 'update_load_obo') {
+    $success = db_update('tripal_cv_obo')
+      ->fields(array(
+        'name' => $uobo_name,
+        'path' => $uobo_url ? $uobo_url : $uobo_file,
+      ))
+      ->condition('obo_id', $obo_id)
+      ->execute();
+    if ($success) {
+      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');
+    }
 
-  tripal_submit_obo_job(array(
-    'obo_id' => $obo_id,
-    'name' => $obo_name,
-    'url' => $obo_url,
-    'file' => $obo_file
-  ));
+  }
+  // If the user requested to update and load then we've already handled the
+  // update now we just need to load.
+  if ($form_state['clicked_button']['#name'] == 'update_load_obo') {
+    tripal_submit_obo_job(array('obo_id' => $obo_id));
+  }
+  if ($form_state['clicked_button']['#name'] == 'add_new_obo') {
+    $success = db_insert('tripal_cv_obo')
+    ->fields(array(
+      'name' => $obo_name,
+      'path' => $obo_url ? $obo_url : $obo_file,
+    ))
+    ->execute();
+    if ($success) {
+      drupal_set_message(t("The vocabulary %vocab has been added.", array('%vocab' => $obo_name)));
+    }
+    else {
+      drupal_set_message(t("The vocabulary %vocab could not be added.", array('%vocab' => $obo_name)), 'error');
+    }
+  }
 }
 
 /**
@@ -1231,3 +1435,8 @@ function tripal_cv_obo_add_dbxref($db_id, $accession, $version='', $description=
   }
   return $result[0];
 }
+
+
+function tripal_cv_obo_form_ajax_callback($form, $form_state) {
+  return $form['obo_existing'];
+}

+ 16 - 10
tripal_cv/tripal_cv.install

@@ -49,13 +49,19 @@ function tripal_cv_requirements($phase) {
  */
 function tripal_cv_install() {
 
-  // add the cv_root_mview
+  // Add the cv_root_mview.
   tripal_cv_add_cv_root_mview();
 
-  // add defaults to the tables that correlate OBO files/references with a chado CV
+  // Add defaults to the tables that correlate OBO files/references with
+  // a chado CV.
   tripal_cv_add_obo_defaults();
 
-  // create the temp table we will use for loading OBO files
+  // Add the Chado ontology CV.
+  $obo_path = '{tripal_cv}/files/cv_property.obo';
+  $obo_id = tripal_insert_obo('Chado CV Properties', $obo_path);
+  tripal_submit_obo_job(array('obo_id' => $obo_id));
+
+  // Create the temp table we will use for loading OBO files.
   tripal_cv_create_tripal_obo_temp();
 }
 
@@ -236,15 +242,15 @@ function tripal_cv_add_cv_root_mview() {
  */
 function tripal_cv_add_obo_defaults() {
 
-  // insert commonly used ontologies into the tables
+  // Insert commonly used ontologies into the tables.
   $ontologies = array(
-    array('Chado Feature Properties', drupal_get_path('module', 'tripal_cv') . '/feature_property.obo'),
-    array('Relationship Ontology', 'http://www.obofoundry.org/ro/ro.obo'),
-    array('Sequence Ontology', 'http://song.cvs.sourceforge.net/*checkout*/song/ontology/so.obo'),
+    array('Relationship Ontology', 'http://purl.obolibrary.org/obo/ro.obo'),
+//    array('Relationship Ontology (older deprecated version)', 'http://www.obofoundry.org/ro/ro.obo'),
+    array('Sequence Ontology', 'https://github.com/The-Sequence-Ontology/SO-Ontologies/blob/master/so-xp-simple.obo'),
     array('Gene Ontology', 'http://www.geneontology.org/ontology/gene_ontology.obo'),
-    array('Cell Ontology', 'http://obo.cvs.sourceforge.net/obo/obo/ontology/anatomy/cell_type/cell.obo?rev=HEAD'),
-    array('Plant Structure Ontology', 'http://palea.cgrb.oregonstate.edu/viewsvn/Poc/trunk/ontology/OBO_format/po_anatomy.obo?view=co'),
-    array('Plant Growth and Development Stages Ontology', 'http://palea.cgrb.oregonstate.edu/viewsvn/Poc/trunk/ontology/OBO_format/po_temporal.obo?view=co')
+//    array('Cell Ontology', 'https://raw.githubusercontent.com/obophenotype/cell-ontology/master/cl.obo'),
+//    array('Plant Structure Ontology', 'http://palea.cgrb.oregonstate.edu/viewsvn/Poc/trunk/ontology/OBO_format/po_anatomy.obo?view=co'),
+//    array('Plant Growth and Development Stages Ontology', 'http://palea.cgrb.oregonstate.edu/viewsvn/Poc/trunk/ontology/OBO_format/po_temporal.obo?view=co')
   );
   foreach ($ontologies as $o) {
     db_query("INSERT INTO {tripal_cv_obo} (name,path) VALUES (:name, :path)", array(':name' => $o[0], ':path' => $o[1]));

+ 0 - 0
tripal_cv/feature_property.obo → tripal_feature/files/feature_property.obo


+ 6 - 0
tripal_feature/tripal_feature.install

@@ -48,6 +48,12 @@ function tripal_feature_requirements($phase) {
  * @ingroup tripal_feature
  */
 function tripal_feature_install() {
+
+  // Add the feature properties vocabulary provided by Chado.
+  $obo_path = '{tripal_feature}/files/feature_property.obo';
+  $obo_id = tripal_insert_obo('Chado Feature Properties', $obo_path);
+  tripal_submit_obo_job(array('obo_id' => $obo_id));
+
   // Add the materialized view.
   tripal_feature_add_organism_count_mview();
 

+ 4 - 3
tripal_featuremap/includes/tripal_featuremap.chado_node.inc

@@ -155,9 +155,6 @@ function chado_featuremap_form($node, &$form_state) {
  */
 function chado_featuremap_validate($node, $form, &$form_state) {
 
-  if ($node->unittype_id == 0) {
-    form_set_error('unittype_id', 'Please provide a unit type for this map.');
-  }
   // We only want to validate when the node is saved.
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
@@ -172,6 +169,10 @@ function chado_featuremap_validate($node, $form, &$form_state) {
     return;
   }
 
+  if ($node->unittype_id == 0) {
+    form_set_error('unittype_id', 'Please provide a unit type for this map.');
+  }
+  
   // trim white space from text fields
   $node->fmapname = property_exists($node, 'fmapname') ? trim($node->fmapname) : '';
 

+ 10 - 10
tripal_organism/includes/tripal_organism.delete.inc

@@ -19,11 +19,11 @@ function tripal_organism_delete_form() {
   }
 
   $form['desc'] = array(
-    '#markup' => t("Use the following form to delete organisms which may or may 
-        not be synced. Please be cautious. Deleting an organism will cause all 
+    '#markup' => t("Use the following form to delete organisms which may or may
+        not be synced. Please be cautious. Deleting an organism will cause all
         data associated with the organism to also be deleted."),
   );
-  
+
   $form['organisms'] = array(
     '#title'       => t('Organism'),
     '#type'        => 'checkboxes',
@@ -55,10 +55,10 @@ function tripal_organism_delete_form_submit($form, &$form_state) {
       $org_ids[] = $id;
     }
   }
-  
+
   if (count($org_ids) > 0) {
     $args = array($org_ids);
-  
+
     tripal_add_job("Delete Organism", 'tripal_organism',
       'tripal_organism_delete_organisms', $args, $user->uid);
     drupal_set_message(t("Organisms will disappear from the list below once the job completes."));
@@ -87,8 +87,8 @@ function tripal_organism_delete_organisms($organisms, $job = NULL) {
   // function which is not prefix with the schema, and an error occurs.
   // Therefore, we set the active database to chado to get around that
   // problem.
-  $previous_db = chado_set_active('chado');
-  
+//  $previous_db = chado_set_active('chado');
+
   // begin the transaction
   $transaction = db_transaction();
   print "\nNOTE: Deleting organisms is performed using a database transaction. \n" .
@@ -97,12 +97,12 @@ function tripal_organism_delete_organisms($organisms, $job = NULL) {
 
   try {
     $values = array(
-      organism_id => $organisms
+      'organism_id' => $organisms
     );
     $num_deletes = chado_select_record('organism', array('count(*) as cnt'), $values);
     print "Deleting " . $num_deletes[0]->cnt . " organisms\n";
     chado_delete_record('organism', $values);
-  
+
     print "Removing orphaned organism pages\n";
     chado_cleanup_orphaned_nodes('organism');
   }
@@ -113,6 +113,6 @@ function tripal_organism_delete_organisms($organisms, $job = NULL) {
     watchdog_exception('tripal_organism', $e);
     return 0;
   }
-  chado_set_active($previous_db);
+//  chado_set_active($previous_db);
   print "\nDone\n";
 }

+ 16 - 19
tripal_pub/includes/tripal_pub.pub_search.inc

@@ -1,9 +1,9 @@
 <?php
 /**
  * @file
- * 
- * Functions responsible for creating the publication search form that 
- * allows a user of the site to search for publications that are currently 
+ *
+ * Functions responsible for creating the publication search form that
+ * allows a user of the site to search for publications that are currently
  * in Chado.
  */
 
@@ -16,7 +16,7 @@ function tripal_pub_search_page() {
 
   // This line may not be required, but on some sites the $_SESSION
   // variable wasn't being set for anonymous users. This line solves that
-  // problem 
+  // problem
   drupal_session_start();
 
   $limit = 25;
@@ -49,7 +49,7 @@ function tripal_pub_search_page() {
     $total_records = 0;
     $pubs = tripal_search_publications($search_array, $offset, $limit, $total_records);
     pager_default_initialize($total_records, $limit, 0);
-    
+
     // iterate through the results and construct the table displaying the publications
     $rows = array();
     $i = $page * $limit + 1;
@@ -96,7 +96,7 @@ function tripal_pub_search_page() {
       'header' => $headers,
       'rows' => $rows,
       'attributes' => array(
-        'id' => 'tripal-pub-search-results-table', 
+        'id' => 'tripal-pub-search-results-table',
         'border' => '0',
         'class' => array('tripal-data-table')
       ),
@@ -147,41 +147,38 @@ function tripal_pub_search_form($form, &$form_state) {
 
   // if the session has variables then use those.  This should only happen when
   // the 'Test Criteria' button is clicked.
+  if (array_key_exists('storage', $form_state)) {
+    $num_criteria = $form_state['storage']['num_criteria'];
+  }
   if (array_key_exists('tripal_pub_search_form', $_SESSION)) {
     $num_criteria = $_SESSION['tripal_pub_search_form']['num_criteria'] ? $_SESSION['tripal_pub_search_form']['num_criteria'] : $num_criteria;
     $from_year    = $_SESSION['tripal_pub_search_form']['from_year']    ? $_SESSION['tripal_pub_search_form']['from_year']    : '';
     $to_year      = $_SESSION['tripal_pub_search_form']['to_year']      ? $_SESSION['tripal_pub_search_form']['to_year']      : '';
   }
   if (array_key_exists('values', $form_state)) {
-    $num_criteria = $form_state['values']['num_criteria'] ? $form_state['values']['num_criteria'] : $num_criteria;
     $from_year    = $form_state['values']['from_year']    ? $form_state['values']['from_year']    : $from_year;
     $to_year      = $form_state['values']['to_year']      ? $form_state['values']['to_year']      : $to_year;
   }
   if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
-    $num_criteria = $form_state['input']['num_criteria'] ? $form_state['input']['num_criteria'] : $num_criteria;
     $from_year    = $form_state['input']['from_year']    ? $form_state['input']['from_year']    : $from_year;
     $to_year      = $form_state['input']['to_year']      ? $form_state['input']['to_year']      : $to_year;
-
   }
 
   if (array_key_exists('triggering_element', $form_state) and
-  $form_state['triggering_element']['#name'] == 'add') {
+      $form_state['triggering_element']['#name'] == 'add') {
     $num_criteria++;
   }
   if (array_key_exists('triggering_element', $form_state) and
-  $form_state['triggering_element']['#name'] == 'remove') {
+      $form_state['triggering_element']['#name'] == 'remove') {
     $num_criteria--;
   }
 
-  $form['num_criteria']= array(
-    '#type'          => 'hidden',
-    '#default_value' => $num_criteria,
-  );
+  $form_state['storage']['num_criteria'] = $num_criteria;
 
   $form['admin-instructions'] = array(
-    '#markup'  =>  tripal_set_message( 
+    '#markup'  =>  tripal_set_message(
       t('Administrators, you can select the fields with which a user can use to search, by checking the desired fields on the ' .
-        l('Publication Module Settings Page', 'admin/tripal/chado/tripal_pub/configuration', array('attributes' => array('target' => '_blank'))) . ' 
+        l('Publication Module Settings Page', 'admin/tripal/chado/tripal_pub/configuration', array('attributes' => array('target' => '_blank'))) . '
         in the section titled "Search Options".  The selected fields will appear in the dropdowns below.'),
       TRIPAL_INFO,
       array('return_html' => 1)),
@@ -464,7 +461,7 @@ function tripal_pub_search_form_submit($form, &$form_state) {
 
 /**
  * Ajax callback to update the form
- * 
+ *
  * @param $form
  *   The form array
  * @param $form_state
@@ -523,7 +520,7 @@ function theme_tripal_pub_search_setup_form_elements($variables) {
     'header' => $headers,
     'rows' => $rows,
     'attributes' => array(
-      'id' => 'tripal-pub-search-form-table', 
+      'id' => 'tripal-pub-search-form-table',
       'border' => '0',
       'class' => 'tripal-data-table'
     ),