瀏覽代碼

Merge branch '7.x-2.x' of github.com:tripal/tripal into 7.x-2.x

Stephen Ficklin 9 年之前
父節點
當前提交
895f8b07fa

+ 7 - 22
tripal_analysis/tripal_analysis.install

@@ -85,7 +85,7 @@ function tripal_analysis_create_analysisfeatureprop() {
 
   // Create analysisfeatureprop table in chado.  This is needed for Chado
   // version 1.11, the table exists in Chado 1.2.
-  if (!db_table_exists('chado.analysisfeatureprop')) {
+  if (!chado_table_exists('analysisfeatureprop')) {
     $sql = "
       CREATE TABLE {analysisfeatureprop} (
         analysisfeatureprop_id SERIAL PRIMARY KEY,
@@ -300,28 +300,13 @@ function tripal_analysis_update_7200() {
   // site upgrade when the tripal_core module is disabled.
   module_load_include('module', 'tripal_core', 'tripal_core');
   tripal_core_import_api();
+  module_load_include('inc', 'tripal_cv', 'api/tripal_cv.api');
 
-  // set the analysis_property as default
+  // Set the analysis_property as default.
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'analysis_property'")->fetchField();
-
-    // Add in the default vocabulary.
-    // If a record already exists then don't change it.
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'analysisprop')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'analysisprop',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-        ))
-        ->execute();
+    $is_set = tripal_get_default_cv('analysisprop', 'type_id');
+    if (!$is_set) {
+      tripal_set_default_cv('analysisprop','type_id', 'analysis_property');
     }
   }
   catch (\PDOException $e) {
@@ -424,4 +409,4 @@ function tripal_analysis_update_7201() {
       ->condition('name', $view_name)
       ->execute();
   }
-}
+}

+ 61 - 101
tripal_contact/tripal_contact.install

@@ -247,51 +247,31 @@ function tripal_contact_update_7200() {
   module_load_include('inc', 'tripal_cv', 'api/tripal_cv.api');
 
 
-  // add the contact_type CV
+  // Add the contact_type CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'tripal_contact'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-      ->fields(array(
-        'name' => 'tripal_contact',
-        'definition' => 'A heirarchical set of terms for describing a contact. It is intended to be used as the default vocabularies in Tripal for contact types and contact properties.'
-      ))
-      ->execute();
-    }
-
-    // make this CV the defaults for the contact properties and contact types
-    // If a record already exists then don't change it.
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'contact')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-           'table_name' => 'contact',
-           'field_name' => 'type_id',
-           'cv_id' => $cv_id
-         ))
-        ->execute();
+    // First we add the cv.
+    // Notice that tripal_insert_cv() will only add it if it doesn't exist already.
+    $cv = tripal_insert_cv(
+      'tripal_contact',
+      'A heirarchical set of terms for describing a contact. It is intended to be used as the default vocabularies in Tripal for contact types and contact properties.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // Set as Default CV for contact types.
+      $is_set = tripal_get_default_cv('contact', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('contact','type_id', 'tripal_contact', $cv_id);
+      }
+
+      // Set as Default CV for contact properties.
+      $is_set = tripal_get_default_cv('contactprop', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('contactprop','type_id', 'tripal_contact', $cv_id);
+      }
     }
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'contactprop')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'contactprop',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-        ))
-        ->execute();
+    else {
+      throw new DrupalUpdateException('Failed to add tripal_contact vocabulary.');
     }
   }
   catch (\PDOException $e) {
@@ -300,70 +280,50 @@ function tripal_contact_update_7200() {
   }
 
 
-  // add the contact_relationship CV
+  // Add the contact_relationship CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'contact_relationship'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-      ->fields(array(
-        'name' => 'contact_relationship',
-        'definition' => 'Contains types of relationships between contacts.'
-      ))
-      ->execute();
+    // First we add the cv.
+    // Notice that tripal_insert_cv() will only add it if it doesn't exist already.
+    $cv = tripal_insert_cv(
+      'contact_relationship',
+      'Contains types of relationships between contacts.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // Set as Default CV for contact relationships.
+      $is_set = tripal_get_default_cv('contact_relationship', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('contact_relationship','type_id', 'contact_relationship', $cv_id);
+      }
     }
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'contact_relationship')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      // add the default
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'contact_relationship',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-          ))
-        ->execute();
+    else {
+      throw new DrupalUpdateException('Failed to add contact_relationship vocabulary.');
     }
   }
   catch (\PDOException $e) {
     $error = $e->getMessage();
-    throw new DrupalUpdateException('Failed to add contact_type vocabulary: '. $error);
+    throw new DrupalUpdateException('Failed to add contact_relationship vocabulary: '. $error);
   }
 
-  // add the contact_type CV
+  // Add the contact_type CV (not default).
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'contact_type'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-      ->fields(array(
-        'name' => 'contact_type',
-        'definition' => 'Contains types of contacts. This can be used if the tripal_contact vocabulary (which is default for contacts in Tripal) is not desired.'
-      ))
-      ->execute();
-    }
+    $cv = tripal_insert_cv(
+      'contact_type',
+      'Contains types of contacts. This can be used if the tripal_contact vocabulary (which is default for contacts in Tripal) is not desired.'
+    );
   }
   catch (\PDOException $e) {
     $error = $e->getMessage();
     throw new DrupalUpdateException('Failed to add contact_type vocabulary: '. $error);
   }
 
-  // add the contact_property CV
+  // Add the contact_property CV (not default).
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'contact_property'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-      ->fields(array(
-        'name' => 'contact_property',
-        'definition' => 'Contains properties for contacts. This can be used if the tripal_contact vocabulary (which is default for contacts in Tripal) is not desired.'
-      ))
-      ->execute();
-    }
+    $cv = tripal_insert_cv(
+      'contact_property',
+      'Contains properties for contacts. This can be used if the tripal_contact vocabulary (which is default for contacts in Tripal) is not desired.'
+    );
   }
   catch (\PDOException $e) {
     $error = $e->getMessage();
@@ -407,25 +367,25 @@ function tripal_contact_update_7201() {
   try {
     $fkey_exists = db_query('SELECT TRUE FROM pg_constraint WHERE conname = :constraint', array(':constraint' => 'contactprop_type_id_fkey'))->fetchField();
     if ($fkey_exists) {
-      db_query('
-        ALTER TABLE chado.contactprop
+      chado_query('
+        ALTER TABLE {contactprop}
         DROP CONSTRAINT contactprop_type_id_fkey CASCADE
       ');
-      db_query('
-        ALTER TABLE chado.contactprop
+      chado_query('
+        ALTER TABLE {contactprop}
         DROP CONSTRAINT contactprop_contact_id_fkey CASCADE
       ');
     }
-    db_query('
-      ALTER TABLE chado.contactprop
+    chado_query('
+      ALTER TABLE {contactprop}
       ADD CONSTRAINT contactprop_type_id_fkey
-      FOREIGN KEY (type_id) REFERENCES chado.cvterm (cvterm_id)
+      FOREIGN KEY (type_id) REFERENCES {cvterm} (cvterm_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
-    db_query('
-      ALTER TABLE chado.contactprop
+    chado_query('
+      ALTER TABLE {contactprop}
       ADD CONSTRAINT contactprop_contact_id_fkey
-      FOREIGN KEY (contact_id) REFERENCES chado.contact (contact_id)
+      FOREIGN KEY (contact_id) REFERENCES {contact} (contact_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
   }

+ 5 - 2
tripal_core/api/tripal_core.chado_general.api.inc

@@ -66,12 +66,15 @@ function chado_set_active($dbname = 'default') {
   }
 
   $previous_db = $active_db = $GLOBALS['chado_active_db'];
-  $search_path = 'public';
+  $search_path = tripal_get_schema_name('drupal');
 
   // Change only if 'chado' has been specified.
+  // Notice that we leave the active_db set as chado but use the possibly user-altered
+  // schema name for the actual search path. This is to keep outward facing mentions of
+  // chado as "chado" while still allowing the user to alter the schema name used.
   if ($dbname == 'chado') {
     $active_db = 'chado';
-    $search_path = 'chado,public';
+    $search_path = tripal_get_schema_name('chado') . ',' . tripal_get_schema_name('drupal');
   }
 
   $settings = array(

+ 5 - 2
tripal_core/api/tripal_core.chado_nodes.relationships.api.inc

@@ -1046,7 +1046,10 @@ function chado_add_node_form_relationships_name_to_id_callback($base_table, $nam
 
   $base_key = $base_table.'_id';
 
-  $query = db_select('chado.'.$base_table, 'b')
+  // determine the chado schema.
+  $chado = tripal_get_schema_name('chado');
+
+  $query = db_select($chado.'.'.$base_table, 'b')
     ->fields('b', array($base_key, $name_field))
     ->condition($name_field, '%' . db_like($string) . '%', 'LIKE');
 
@@ -1065,4 +1068,4 @@ function chado_add_node_form_relationships_name_to_id_callback($base_table, $nam
 
   // return for JS
   drupal_json_output($matches);
-}
+}

+ 121 - 11
tripal_core/api/tripal_core.chado_nodes.title_and_path.api.inc

@@ -1138,6 +1138,60 @@ function chado_node_get_token_format($application, $content_type, $options = arr
   }
 }
 
+/**
+ * Generate a Readable but not necessarily unique format based on a given primary
+ * key token.
+ *
+ * For example, given the token [feature.type_id>cvterm.cvterm_id] you don't
+ * want the actual id indexed but instead would want the term name, [feature.type_id>cvterm.name]
+ */
+function chado_node_get_readable_format($token) {
+
+  // First, lets break down the token into it's parts.
+  // 1. Remove containing brackets.
+  $parts = str_replace(array('[',']'),'',$token);
+  // 2. Break into table clauses.
+  $parts = explode('>',$parts);
+  // 3. Break each table clause into table & field.
+  foreach ($parts as $k => $v) {
+    $parts[$k] = explode('.', $v);
+    if (sizeof($parts[$k]) == 1) {
+      $parts[$k] = explode(':', $v);
+    }
+  }
+  $last_k = $k;
+
+  // Now, we want to find readable fields for the last table specified in the token.
+  // (ie: for cvterm in [feature.type_id>cvterm.cvterm_id])
+  $table = $parts[$last_k][0];
+  $format = array();
+  if ($table == 'organism') {
+    $format[] = preg_replace('/(\w+)\]$/', 'genus]', $token);
+    $format[] = preg_replace('/(\w+)\]$/', 'species]', $token);
+    $format[] = preg_replace('/(\w+)\]$/', 'common_name]', $token);
+    $format = $format[0] . ' ' . $format[1] . ' (' . $format[2] . ')';
+  }
+  elseif ($table == 'dbxref') {
+    $format[] = preg_replace('/(\w+)\]$/', 'accession]', $token);
+    $format[] = preg_replace('/(\w+)\]$/', 'db_id>db.name]', $token);
+    $format = $format[0] . ' (' . $format[1] . ')';
+  }
+  else {
+    $schema = chado_get_schema($table);
+    foreach ($schema['fields'] as $field_name => $details) {
+      if (preg_match('/name/',$field_name)) {
+        $format[] = preg_replace('/(\w+)\]$/', $field_name.']', $token);
+      }
+    }
+    $format = implode(', ',$format);
+  }
+  if (empty($format)) {
+    return FALSE;
+  }
+
+  return $format;
+}
+
 /**
  * Generate the unique constraint for a given base table using the
  * Chado Schema API definition
@@ -1304,12 +1358,14 @@ function chado_node_generate_tokens($base_table, $token_prefix = FALSE, $locatio
  * @return
  *   The value of the token
  */
-function chado_get_token_value($token_info, $node) {
+function chado_get_token_value($token_info, $node, $options = array()) {
 
   $token = $token_info['token'];
   $table = $token_info['table'];
   $var = $node;
 
+  $supress_errors = (isset($options['supress_errors'])) ? $options['supress_errors'] : FALSE;
+
   // Iterate through each portion of the location string. An example string
   // might be:  stock > type_id > name.
   $location = explode('>', $token_info['location']);
@@ -1325,11 +1381,13 @@ function chado_get_token_value($token_info, $node) {
         $var = $var->$index;
       }
       else {
-        tripal_report_error('chado_node_api', TRIPAL_WARNING,
-          'Tokens: Unable to determine the value of %token. Things went awry when trying ' .
-          'to access \'%index\' for the following: \'%var\'.',
-          array('%token' => $token, '%index' => $index, '%var' => print_r($var,TRUE))
-        );
+        if (!$supress_errors) {
+          tripal_report_error('chado_node_api', TRIPAL_WARNING,
+            'Tokens: Unable to determine the value of %token. Things went awry when trying ' .
+            'to access \'%index\' for the following: \'%var\'.',
+            array('%token' => $token, '%index' => $index, '%var' => print_r($var,TRUE))
+          );
+        }
         return '';
       }
     }
@@ -1339,11 +1397,13 @@ function chado_get_token_value($token_info, $node) {
       $var = $var[$index];
     }
     else {
-      tripal_report_error('chado_node_api', TRIPAL_WARNING,
-        'Tokens: Unable to determine the value of %token. Things went awry when trying ' .
-        'to access \'%index\' for the following: \'%var\'.',
-        array('%token' => $token, '%index' => $index, '%var' => print_r($var,TRUE))
-      );
+      if (!$supress_errors) {
+        tripal_report_error('chado_node_api', TRIPAL_WARNING,
+          'Tokens: Unable to determine the value of %token. Things went awry when trying ' .
+          'to access \'%index\' for the following: \'%var\'.',
+          array('%token' => $token, '%index' => $index, '%var' => print_r($var,TRUE))
+        );
+      }
       return '';
     }
   }
@@ -1388,6 +1448,56 @@ function chado_node_format_tokens($tokens) {
   return theme_table($table);
 }
 
+/**
+ * Returns the "location" as specified in the token information based on the token.
+ */
+function chado_node_get_location_from_token($token) {
+
+  if (is_array($token) and isset($token['location'])) {
+    return $token['location'];
+  }
+  // If we have been given the token as a string, we can still determine the location
+  // but it takes more work...
+  // First, lets clarify what the location is: the location shows which keys in which
+  // order need to be travelled in order to access the value. For example, the token
+  // [feature.organism_id>organism.genus] would have a location of
+  // feature > organism_id > genus to show that the value is at
+  // $node->feature->organism->genus.
+  elseif (is_string($token)) {
+
+    // First, lets break down the token into it's parts.
+    // 1. Remove containing brackets.
+    $parts = str_replace(array('[',']'),'',$token);
+    // 2. Break into table clauses.
+    $parts = explode('>',$parts);
+    // 3. Break each table clause into table & field.
+    foreach ($parts as $k => $v) {
+      $parts[$k] = explode('.', $v);
+      if (sizeof($parts[$k]) == 1) {
+        $parts[$k] = explode(':', $v);
+      }
+    }
+
+    // This is a base level field that is not a foreign key.
+    if (sizeof($parts) == 1 AND sizeof($parts[0]) == 2) {
+      return $parts[0][0] . ' > ' . $parts[0][1];
+    }
+    // Darn, we have at least one foreign key...
+    elseif (sizeof($parts) > 1 AND sizeof($parts[0]) == 2) {
+      $location = $parts[0][0] . ' > ' . $parts[0][1];
+      foreach ($parts as $k => $p) {
+        if ($k != 0 AND isset($p[1])) {
+          $location .= ' > ' . $p[1];
+        }
+      }
+      return $location;
+    }
+    else {
+      return FALSE;
+    }
+  }
+}
+
 /**
  * This sorts tokens first by depth (ie: stock.* is before stock.*>subtable.*) and
  * then alphabetically within a level (ie: stock.name comes before stock.type_id)

+ 118 - 7
tripal_core/api/tripal_core.chado_query.api.inc

@@ -1489,7 +1489,7 @@ function chado_select_record_check_value_type(&$op, &$value, $type) {
  * @ingroup tripal_chado_query_api
  */
 function chado_query($sql, $args = array()) {
-  $is_local = $GLOBALS["chado_is_local"];
+  $is_local = isset($GLOBALS["chado_is_local"]) && $GLOBALS["chado_is_local"];
 
   // Args should be an array
   if (!is_array($args)) {
@@ -1510,17 +1510,28 @@ function chado_query($sql, $args = array()) {
     // Prefix the tables with their correct schema.
     // Chado tables should be enclosed in curly brackets (ie: {feature} )
     // and Drupal tables should be enclosed in square brackets (ie: [tripal_jobs] ).
-    // @todo: remove assumption that the chado schema is called 'chado' and the
-    // drupal schema is called 'public'.
-    $sql = preg_replace('/\{(.*?)\}/', 'chado.$1', $sql);
-    $sql = preg_replace('/\[(\w+)\]/', 'public.$1', $sql);
+    $chado_schema_name = tripal_get_schema_name('chado');
+    $drupal_schema_name = tripal_get_schema_name('drupal');
+    $sql = preg_replace('/\{(.*?)\}/', $chado_schema_name.'.$1', $sql);
+    $sql = preg_replace('/\[(\w+)\]/', $drupal_schema_name.'.$1', $sql);
+
+    // Add an alter hook to allow module developers to change the query right before it's
+    // executed. Since all queriying of chado by Tripal eventually goes through this
+    // function, we only need to provide an alter hook at this point in order to ensure
+    // developers have complete control over the query being executed. For example,
+    // a module developer might want to remove schema prefixing from queries and rely
+    // on the search path. This alter hook would allow them to do that by implementing
+    // mymodule_chado_query_alter($sql, $args) and using a regular expression to remove
+    // table prefixing from the query.
+    // @see hook_chado_query_alter().
+    drupal_alter('chado_query', $sql, $args);
 
     // The featureloc table has some indexes that use function that call other
     // functions and those calls do not reference a schema, therefore, any
     // tables with featureloc must automaticaly have the chado schema set as
     // active to find.
-    if (preg_match('/chado.featureloc/i', $sql) or preg_match('/chado.feature/i', $sql)) {
-      $previous_db = chado_set_active('chado') ;
+    if (preg_match('/'.$chado_schema_name.'.featureloc/i', $sql) or preg_match('/'.$chado_schema_name.'.feature/i', $sql)) {
+      $previous_db = chado_set_active('chado');
       $results = db_query($sql, $args);
       chado_set_active($previous_db);
     }
@@ -1552,6 +1563,42 @@ function chado_query($sql, $args = array()) {
   return $results;
 }
 
+/**
+ * This hook provides a way for module developers to alter any/all queries on the chado
+ * schema by Tripal.
+ *
+ * Example: a module developer might want to remove schema prefixing from queries and rely
+ * on the search path. This alter hook would allow them to do that by implementing
+ * mymodule_chado_query_alter($sql, $args) and using a regular expression to remove
+ * table prefixing from the query.
+ *
+ * @param $sql
+ *    A string describing the SQL query to be executed by Tripal. All parameters should be
+ *    indicated by :tokens with values being in the $args array and all tables should
+ *    be prefixed with the schema name described in tripal_get_schema_name().
+ * @param $args
+ *    An array of arguements where the key is the token used in $sql (for example, :value)
+ *    and the value is the value you would like substituted in.
+ */
+function hook_chado_query_alter(&$sql, &$args) {
+
+  // The following code is an example of how this alter function might be used.
+  // Say you would like only a portion of node => feature connections available
+  // for a period of time or under a specific condition. To "hide" the other connections
+  // you might create a temporary view of the chado_feature table that only includes
+  // the connections you would like to be available. In order to ensure this view
+  // is used rather than the original chado_feature table you could alter all Tripal
+  // queries referring to chado_feature to instead refer to your view.
+  if (preg_match('/(\w+)\.chado_feature/', $sql, $matches)) {
+
+      $sql = str_replace(
+        $matches[1] . '.chado_feature',
+        'chado_feature_view',
+        $sql
+      );
+  }
+}
+
 /**
  * Use this function instead of pager_query() when selecting a
  * subset of records from a Chado table.
@@ -1609,6 +1656,7 @@ function chado_pager_query($query, $args, $limit, $element, $count_query = '') {
   $results = chado_query($query, $args);
   return $results;
 }
+
 /**
  * A function to retrieve the total number of records for a pager that
  * was generated using the chado_pager_query() function
@@ -1749,3 +1797,66 @@ function chado_schema_get_foreign_key($table_desc, $field, $values, $options = N
 
   return array();
 }
+
+/**
+ * Retrieve the name of the PostgreSQL schema housing Chado or Drupal.
+ *
+ * @param $schema
+ *   Wehter you want the schema name for 'chado' or 'drupal'. Chado is the default.
+ * @return
+ *   The name of the PostgreSQL schema housing the $schema specified.
+ */
+function tripal_get_schema_name($schema = 'chado') {
+
+  // First we will set our default. This is what will be returned in most cases.
+  if ($schema == 'chado') {
+    $schema_name = 'chado';
+  }
+  else {
+    $schema_name = 'public';
+  }
+
+  // There are cases where modules or admin might need to change the default
+  // names for the schema. Thus we provide an alter hook here to allow
+  // the names to be changed and ensure that schema names are never hardcoded
+  // directly into queries.
+  $context = array('schema' => $schema);
+  drupal_alter('tripal_get_schema_name', $schema_name, $context);
+
+  return $schema_name;
+}
+
+/**
+ * Alter the name of the schema housing Chado and/or Drupal.
+ *
+ * This example implementation shows a solution for the case where your chado database
+ * was well established in the "public" schema and you added Drupal later in a
+ * "drupal" schema. Please note that this has not been tested and while we can ensure
+ * that Tripal will work as expected, we have no control over whether Drupal is
+ * compatible with not being in the public schema. That's why we recommened the
+ * organization we have (ie: Chado in a "chado" schema and Drupal in the "public schema).
+ *
+ * @param $schema_name
+ *   The current name of the schema as known by Tripal. This is likely the default
+ *   set in tripal_get_schema_name() but in the case of multiple alter hooks, it might
+ *   be different.
+ * @param $context
+ *   This is an array of items to provide context.
+ *     - schema: this is the schema that was passed to tripal_get_schema_name() and will
+ *       be either "chado" or "drupal". This should be used to determine you are changing
+ *       the name of the correct schema.
+ */
+function hook_tripal_get_schema_name_alter($schema_name, $context) {
+
+  // First we check which schema was passed to chado_get_schema().
+  // Notice that we do not use $schema_name since it may already have
+  // been altered by another module.
+  if ($context['schema'] == 'chado') {
+    $schema_name = 'public';
+  }
+  // Notice that we use elseif to capture the second case rather than else. This
+  // avoids the assumption that there is only one chado and one drupal schema.
+  elseif ($context['schema'] == 'drupal') {
+    $schema_name = 'drupal';
+  }
+}

+ 13 - 10
tripal_core/api/tripal_core.chado_schema.api.inc

@@ -30,8 +30,10 @@
  * is necessary because Drupa's db_table_exists will not
  * look in any other schema but the one were Drupal is installed
  *
+ * @param $table
+ *   The name of the chado table whose existence should be checked.
  * @return
- *   TRUE/FALSE depending upon whether it exists
+ *   TRUE if the table exists in the chado schema and FALSE if it does not.
  *
  * @ingroup tripal_chado_schema_api
  */
@@ -45,10 +47,10 @@ function chado_table_exists($table) {
     FROM information_schema.tables
     WHERE
       table_name = :table_name AND
-      table_schema = 'chado' AND
-      table_catalog = '$default_db'
+      table_schema = :chado AND
+      table_catalog = :default_db
   ";
-  $results = db_query($sql, array(':table_name' => $table));
+  $results = db_query($sql, array(':table_name' => $table, ':chado' => tripal_get_schema_name('chado'), ':default_db' => $default_db));
   $exists = $results->fetchObject();
   if (!$exists) {
     return FALSE;
@@ -152,9 +154,9 @@ function chado_is_local() {
     FROM pg_namespace
     WHERE
       has_schema_privilege(nspname, 'USAGE') AND
-      nspname = 'chado'
+      nspname = :chado
   ";
-  $results = db_query($sql);
+  $results = db_query($sql, array(':chado' => tripal_get_schema_name('chado')));
   $name = $results->fetchObject();
   if ($name) {
     variable_set('chado_schema_exists', FALSE);
@@ -178,7 +180,7 @@ function chado_is_installed() {
   global $databases;
 
   // first check if chado is in the $databases variable of the settings.php file
-  if (array_key_exists('chado', $databases)) {
+  if (array_key_exists(tripal_get_schema_name('chado'), $databases)) {
     return TRUE;
   }
 
@@ -220,7 +222,7 @@ function chado_get_version($exact = FALSE, $warn_if_unsupported = FALSE) {
   if (!$chado_exists) {
     // if it's not in the drupal database check to see if it's specified in the $db_url
     // in the settings.php
-    if (!array_key_exists('chado', $databases)) {
+    if (!array_key_exists(tripal_get_schema_name('chado'), $databases)) {
       // if it's not in the drupal database or specified in the $db_url then
       // return uninstalled as the version
       return 'not installed';
@@ -232,7 +234,8 @@ function chado_get_version($exact = FALSE, $warn_if_unsupported = FALSE) {
   }
   else {
     $is_local = 1;
-    $prop_exists = db_table_exists('chado.chadoprop');
+    // @todo we need a chado aware db_table_exists.
+    $prop_exists = db_table_exists(tripal_get_schema_name('chado').'.chadoprop');
   }
 
   // if the table doesn't exist then we don't know what version but we know
@@ -418,4 +421,4 @@ function chado_get_custom_table_schema($table) {
   else {
     return unserialize($custom->schema);
   }
-}
+}

+ 4 - 2
tripal_core/api/tripal_core.custom_tables.api.inc

@@ -122,6 +122,8 @@ function chado_create_custom_table($table, $schema, $skip_if_exists = 1, $mview_
   global $databases;
   $created = 0;
   $recreated = 0;
+  $chado_schema = tripal_get_schema_name('chado');
+  $chado_dot = $chado_schema . '.';
 
   $transaction = db_transaction();
   try {
@@ -135,7 +137,7 @@ function chado_create_custom_table($table, $schema, $skip_if_exists = 1, $mview_
 
     // if the table does not exist then create it
     if (!$exists) {
-      $ret = db_create_table('chado.' . $table, $schema);
+      $ret = db_create_table($chado_dot . $table, $schema);
       $created = 1;
     }
 
@@ -150,7 +152,7 @@ function chado_create_custom_table($table, $schema, $skip_if_exists = 1, $mview_
       if (array_key_exists('referring_tables', $new_schema)) {
         unset($new_schema['referring_tables']);
       }
-      db_create_table('chado.' . $table, $new_schema);
+      db_create_table($chado_dot . $table, $new_schema);
       $recreated = 1;
     }
 

+ 1 - 1
tripal_core/api/tripal_core.mviews.api.inc

@@ -400,7 +400,7 @@ function tripal_delete_mview($mview_id) {
   db_query($sql);
 
   // does the table already exist?
-  $mview_exists = db_table_exists('chado.' . $mview->mv_table);
+  $mview_exists = chado_table_exists($mview->mv_table);
 
   // drop the table from chado if it exists
   if ($mview_exists) {

+ 39 - 30
tripal_core/includes/tripal_core.chado_install.inc

@@ -322,6 +322,10 @@ function tripal_core_upgrade_chado_1_11_to_1_2() {
  */
 function tripal_core_reset_chado_schema() {
 
+  // determine the schema name.
+  $chado_schema = tripal_get_schema_name('chado');
+  $chado_dot = $chado_schema . '.';
+
   // drop current chado and chado-related schema
   if (chado_dbschema_exists('genetic_code')) {
     print "Dropping existing 'genetic_code' schema\n";
@@ -337,12 +341,12 @@ function tripal_core_reset_chado_schema() {
   }
   if (chado_dbschema_exists('chado')) {
     print "Dropping existing 'chado' schema\n";
-    db_query("drop schema chado cascade");
+    db_query("drop schema $chado_schema cascade");
   }
 
   // create the new chado schema
   print "Creating 'chado' schema\n";
-  db_query("create schema chado");
+  db_query("create schema $chado_schema");
   if (chado_dbschema_exists('chado')) {
     // before creating the plpgsql language let's check to make sure
     // it doesn't already exists
@@ -370,8 +374,12 @@ function tripal_core_install_sql($sql_file) {
 
   $chado_local = chado_dbschema_exists('chado');
 
+  // determine the schema name.
+  $chado_schema = tripal_get_schema_name('chado');
+  $chado_dot = $chado_schema . '.';
+
   if ($chado_local) {
-    db_query("set search_path to chado");
+    db_query("set search_path to $chado_schema");
   }
   print "Loading $sql_file...\n";
   $lines = file($sql_file, FILE_SKIP_EMPTY_LINES);
@@ -403,11 +411,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 and !$in_function) {
       $stack[] = 'table';
-      $line = preg_replace("/public\./", "chado.", $line);
+      $line = preg_replace("/public\./", $chado_dot, $line);
     }
     if (preg_match('/^\s*ALTER\s+TABLE\s+/i', $line) and !$in_string and !$in_function) {
       $stack[] = 'alter_table';
-      $line = preg_replace("/public\./", "chado.", $line);
+      $line = preg_replace("/public\./", $chado_dot, $line);
     }
     if (preg_match('/^\s*SET/i', $line) and !$in_string and !$in_function) {
       $stack[] = 'set';
@@ -417,27 +425,27 @@ function tripal_core_install_sql($sql_file) {
     }
     if (preg_match('/^\s*CREATE\s+SEQUENCE/i', $line) and !$in_string and !$in_function) {
       $stack[] = 'sequence';
-      $line = preg_replace("/public\./", "chado.", $line);
+      $line = preg_replace("/public\./", $chado_dot, $line);
     }
     if (preg_match('/^\s*CREATE\s+(?:OR\s+REPLACE\s+)*VIEW/i', $line) and !$in_string and !$in_function) {
       $stack[] = 'view';
-      $line = preg_replace("/public\./", "chado.", $line);
+      $line = preg_replace("/public\./", $chado_dot, $line);
     }
     if (preg_match('/^\s*COMMENT/i', $line) and !$in_string and sizeof($stack)==0 and !$in_function) {
       $stack[] = 'comment';
-      $line = preg_replace("/public\./", "chado.", $line);
+      $line = preg_replace("/public\./", $chado_dot, $line);
     }
     if (preg_match('/^\s*CREATE\s+(?:OR\s+REPLACE\s+)*FUNCTION/i', $line) and !$in_string and !$in_function) {
       $in_function = TRUE;
       $stack[] = 'function';
-      $line = preg_replace("/public\./", "chado.", $line);
+      $line = preg_replace("/public\./", $chado_dot, $line);
     }
     if (preg_match('/^\s*CREATE\s+INDEX/i', $line) and !$in_string and !$in_function) {
       $stack[] = 'index';
     }
     if (preg_match('/^\s*INSERT\s+INTO/i', $line) and !$in_string and !$in_function) {
       $stack[] = 'insert';
-      $line = preg_replace("/public\./", "chado.", $line);
+      $line = preg_replace("/public\./", $chado_dot, $line);
     }
     if (preg_match('/^\s*CREATE\s+TYPE/i', $line) and !$in_string and !$in_function) {
       $stack[] = 'type';
@@ -476,25 +484,25 @@ function tripal_core_install_sql($sql_file) {
     if (strcmp($stack[sizeof($stack)-1], 'table') == 0 and preg_match('/\);\s*$/', $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'alter_table') == 0 and preg_match('/;\s*$/', $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'alter_table') == 0 and preg_match('/;\s*$/', $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'set') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'set') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'schema') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'schema') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'sequence') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'sequence') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'view') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'view') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'comment') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'comment') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'function') == 0) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'function') == 0) {
 
       if(preg_match('/LANGUAGE.*?;\s*$/i', $line)) {
         $type = array_pop($stack);
@@ -515,37 +523,37 @@ function tripal_core_install_sql($sql_file) {
        // print "FUNCTION ($i): $line";
       }
     }
-    if (strcmp($stack[sizeof($stack)-1], 'index') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'index') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'insert') == 0 and preg_match('/\);\s*$/', $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'insert') == 0 and preg_match('/\);\s*$/', $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'type') == 0 and preg_match('/\);\s*$/', $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'type') == 0 and preg_match('/\);\s*$/', $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'grant') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'grant') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'aggregate') == 0 and preg_match('/\);\s*$/', $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'aggregate') == 0 and preg_match('/\);\s*$/', $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'drop_function') == 0 and preg_match('/;\s*$/i', $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'drop_function') == 0 and preg_match('/;\s*$/i', $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'drop_view') == 0 and preg_match('/;\s*$/i', $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'drop_view') == 0 and preg_match('/;\s*$/i', $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'drop_index') == 0 and preg_match("/;\s*$/i", $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'drop_index') == 0 and preg_match("/;\s*$/i", $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'drop_seq') == 0 and preg_match("/;\s*$/i", $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'drop_seq') == 0 and preg_match("/;\s*$/i", $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'alter_type') == 0 and preg_match('/;\s*$/i', $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'alter_type') == 0 and preg_match('/;\s*$/i', $line)) {
       $type = array_pop($stack);
     }
-    if (strcmp($stack[sizeof($stack)-1], 'alter_seq') == 0 and preg_match('/;\s*$/i', $line)) {
+    elseif (strcmp($stack[sizeof($stack)-1], 'alter_seq') == 0 and preg_match('/;\s*$/i', $line)) {
       $type = array_pop($stack);
     }
     // if we're in a recognized SQL statement then let's keep track of lines
@@ -563,7 +571,7 @@ function tripal_core_install_sql($sql_file) {
       // rewrite the set search_path to make 'public' be 'chado', but only if the
       // chado schema exists
       if (strcmp($type, 'set') == 0 and $chado_local) {
-        $query = preg_replace("/public/m", "chado", $query);
+        $query = preg_replace("/public/m", $chado_schema, $query);
       }
 
       // execute the statement
@@ -593,5 +601,6 @@ function tripal_core_install_sql($sql_file) {
  */
 function tripal_core_chado_install_done() {
 
-  db_query("set search_path to default");
+  $drupal_schema = tripal_get_schema_name('drupal');
+  db_query("set search_path to $drupal_schema");
 }

+ 1 - 1
tripal_core/includes/tripal_core.custom_tables.inc

@@ -328,7 +328,7 @@ function tripal_custom_tables_form_validate($form, &$form_state) {
         $results = db_query($sql, array(':table_id' => $table_id));
         $ct = $results->fetchObject();
         if ($ct->table_name != $schema_array['table']) {
-          $exists = db_table_exists('chado.' . $schema_array['table']);
+          $exists = chado_table_exists($schema_array['table']);
           if ($exists) {
             form_set_error($form_state['values']['schema'],
               t("The table name already exists, please choose a different name."));

+ 439 - 0
tripal_core/includes/tripal_core.search.inc

@@ -0,0 +1,439 @@
+<?php
+/**
+ * @file
+ * Adds support for Drupal indexing of Chado.
+ * It's important to note that not all of Chado is indexed but instead
+ * Only fields indicated in hook_search_include_chado_fields().
+ */
+
+/**
+ * Implements hook_search_include_chado_fields().
+ *
+ * This hook allows Tripal Admin/modules to specify which chado fields should be indexed
+ * for searching in a simple manner.
+ *
+ * @return
+ *   An array of chado fields you would like available for indexing. Each element should
+ *   be the name of the table followed by the field and separated by a period. For example.
+ *   feature.uniquename to indicate the uniquename field from the feature table.
+ */
+function tripal_core_search_include_chado_fields() {
+  return array(
+    'organism.genus',
+    'organism.species',
+  );
+}
+
+/**
+ * Implements hook_entity_property_info_alter().
+ *
+ * This is where we actually add the properties to the node entity in order to indicate
+ * which chado fields should be indexed.
+ */
+function tripal_core_entity_property_info_alter(&$info) {
+
+  // We provide a hook to allow Tripal admin to easily add fields to the search api.
+  // We want to invoke all implementations of that hook now for use below.
+  $fields_to_include = module_invoke_all('search_include_chado_fields');
+  $fields_to_include = array_unique($fields_to_include);
+
+  // Retrieve information for all nodes.
+  // We focus on nodes at this point because we need to link search results back to
+  // the entity and we have no entites for non-node chado content in Tripal2.
+  $node_info = module_invoke_all('node_info');
+
+  foreach ($node_info as $n) {
+
+    // Now keep in mind this hook is defined for ALL THE NODE TYPES and we only want
+    // to add extra support for chado so we onle care about chado node types.
+    // We can distinguish chado node types from all others by the existence of
+    // the 'chado_node_api' key which is used for all sorts of beautiful tripal/chado
+    // node integration (ie: adding properties, relationships and dbxrefs to node forms).
+    if (isset($n['chado_node_api'])) {
+      $schema = chado_get_schema($n['chado_node_api']['base_table']);
+
+      // Now we are going to start by adding some defaults. It feels safe to say, we
+      // probably want to index all the "names" so we are going to look through
+      // all the fields and if they contain "name" we are going to add them automatically.
+      foreach ($schema['fields'] as $field_name => $details) {
+
+        $machine_name = $n['chado_node_api']['base_table'] . '.' . $field_name;
+
+        // Try to create a readable label.
+        $label = ucwords(str_replace(array('.','_'),' ',$machine_name));
+
+        // We want to add all name fields and any fields previously indicated to be indexed.
+        if (preg_match('/name/', $field_name) OR in_array($machine_name, $fields_to_include)) {
+
+          if (!isset($info['node']['bundles'][ $n['base'] ]['properties'][$machine_name])) {
+            $info['node']['bundles'][ $n['base'] ]['properties'][$machine_name] = array(
+              'label' => $label,
+              'description' => $details['description'],
+              'type' => ($details['type'] == 'varchar') ? 'text' : $details['type'],
+              'schema field' => '[' . $machine_name . ']',
+              // The following getter callback is a generic function that can retrieve
+              // values for any chado field.
+              'getter callback' => 'tripal_search_chado_token_getter_callback'
+            );
+          }
+        }
+      }
+
+      // We want to add any base foreign keys. This allows you to search for all features
+      // from a given organism. Furthermore, we want to add a single field for each foreign
+      // key that will span content types in order to be exposed as facets.
+      foreach ($schema['foreign keys'] as $table => $fk_details) {
+        foreach ($fk_details['columns'] as $left_field => $right_field) {
+
+          $machine_name = $n['chado_node_api']['base_table'] . '.' . $left_field;
+          $field_details = $schema['fields'][$left_field];
+
+          // Try to create a readable label.
+          $label = $table . ' (' . $machine_name . ')';
+          if (preg_match('/(\w+)_id/',$left_field,$matches)) {
+            // Key only field.
+            $key_label = ucwords(str_replace('_', ' ', $matches[1]));
+
+            // Expanded field.
+            $label = str_replace('_', ' ', $n['chado_node_api']['base_table']);
+            $label .= ' ' . str_replace('_', ' ', $matches[1]);
+            $label = ucwords($label);
+          }
+
+          $keytoken = '[BASE.' . $left_field . '>' . $table . '.' . $right_field . ']';
+          $format = chado_node_get_readable_format($keytoken);
+
+          // First, create the key version. This is best used for facets since it
+          // won't/can't be tokenized along with the other fields. This will be shared
+          // among node types to facillitate use as a facet.
+          $info['node']['properties'][$table . '.' . $right_field .' key'] = array(
+            'label' => $key_label . ' (All Content Types)',
+            'description' => $field_details['description'],
+            'type' => 'text',
+            // We include both the token for the current node type and the token for
+            // the parent table. That way the organism node will appear in the results
+            // for the organism key.
+            'schema field' => $format,
+            // The following getter callback is a generic function that can retrieve
+            // values for any chado foreign key.
+            'getter callback' => 'tripal_search_chado_token_across_nodetypes_getter_callback'
+          );
+
+          $pretoken = '[' . $n['chado_node_api']['base_table'] . '.' . $left_field . '>' . $table . '.' . $right_field . ']';
+          $format = chado_node_get_readable_format($pretoken);
+
+          // Add a more readable version that will be tokenized so users can
+          // search for fruitfly and get all features with that as an organism.
+          $info['node']['bundles'][ $n['base'] ]['properties'][$machine_name .' expanded'] = array(
+            'label' => $label . ' (Expanded)',
+            'description' => $field_details['description'],
+            'type' => 'text',
+            'schema field' => $format,
+            // The following getter callback is a generic function that can retrieve
+            // values for any chado foreign key.
+            'getter callback' => 'tripal_search_chado_token_getter_callback'
+          );
+        }
+      }
+    }
+  }
+
+  // Provide our own hook for altering properties to make it easier for our users.
+  drupal_alter('tripal_search_properties', $info);
+}
+
+/**
+ * Allows tripal admin to alter entity property information after it has. This is currently
+ * being used to indicate chado fields to be indexed for search.
+ *
+ * NOTE: If you simply need to add a field to be indexed, use hook_search_include_chado_fields()
+ * which provides the much easier method of simply listing fields to include.
+ *
+ * This function is most useful if you want to change the way the value is retrieved
+ * (done by changing the 'getter callback') or add your own custom computed field.
+ */
+function hook_tripal_search_properties_alter(&$info) { }
+
+/**
+ * Implements a getter callback for chado token formats.
+ *
+ * A chado token format is a string containing chado tokens.
+ *
+ * Chado tokens are expected to follow the format of tokens auto-generated using
+ *   chado_node_generate_tokens(). For example, [feature.uniquename] indicates you
+ *   should return the uniquename of a feature node and [feature.organism_id>organism.species]
+ *   indicates you should return the organism genus of the feature node.
+ *
+ * The chado token format must be stored in the 'schema field' when defining the property in
+ *  hook_entity_property_info() in order for this getter to work.
+ *
+ * @param $data
+ *   The entity object (in our case the node we need to retrieve feature properties for).
+ * @param $options
+ * @param $field_name
+ *   The machine name for the entity property.
+ * @param $info
+ *   The full property definition from entity property info.
+ *
+ * @return
+ *   A string representing the "value" of the field.
+ */
+function tripal_search_chado_token_getter_callback($data, $options, $field_name, $type, $info) {
+
+  if (isset($data->nid)) {
+    if (isset($info['schema field'])) {
+      $format = $info['schema field'];
+
+      // Determine our base table so we know if this is even the right node type.
+      if (preg_match('/\[(\w+)\.(\w+)/',$format, $matches)) {
+        $base_table = $matches[1];
+        $field_name = $matches[2];
+
+        // For some weird reason nodes of all types are trying to get a value for fields
+        // that we defined as specific to a given node type (ie: bundle). As such we need
+        // this check here to ensure this field is actually for this node type.
+        if (!isset($data->{$base_table})) return NULL;
+
+        $format = tripal_core_get_token_value_for_property($base_table, $field_name, $format, $data, $info);
+        return $format;
+      }
+      else {
+        // Not able to determine table?
+        tripal_report_error(
+          'tripal_search',
+          TRIPAL_ERROR,
+          'Unable to extract the base table from the format (:format) for :field because it didn\'t match the expected format: [tablename.field...',
+          array(':field' => $field_name, ':format' => $format)
+        );
+        return NULL;
+      }
+    }
+    else {
+      tripal_report_error(
+        'tripal_search',
+        TRIPAL_ERROR,
+        'Unable to get value for :field because the schema field was not set.',
+        array(':field' => $field_name)
+      );
+      return NULL;
+    }
+  }
+}
+
+/**
+ * Implements a getter callback for foreign keys collon between content types.
+ *
+ * @param $data
+ *   The entity object (in our case the node we need to retrieve feature properties for).
+ * @param $options
+ * @param $field_name
+ *   The machine name for the entity property.
+ * @param $info
+ *   The full property definition from entity property info.
+ *
+ * @return
+ *   A string representing the "value" of the field.
+ */
+function tripal_search_chado_token_across_nodetypes_getter_callback($data, $options, $field_name, $type, $info) {
+
+  // First, make sure this is a chado node.
+  // Assumption #1: All chado node types are prefixed with chado_
+  if (isset($data->nid)) {
+    if (preg_match('/^chado_(\w+)/',$data->type,$matches)) {
+      if (isset($info['schema field'])) {
+
+        // Assumption #2: The base table is the suffix of the node type.
+        $base_table = $matches[1];
+
+        // Substitute in the  base table for "BASE" in the schema field.
+        $format = str_replace('BASE', $base_table, $info['schema field']);
+
+        // Replace all tokens for values and return the result.
+        $format = tripal_core_get_token_value_for_property($base_table, $field_name, $format, $data, $info);
+        return $format;
+      }
+      else {
+        // Not able to determine table?
+        tripal_report_error(
+          'tripal_search',
+          TRIPAL_ERROR,
+          'Unable to extract the base table from the format (:format) for :field because it didn\'t match the expected format: [tablename.field...',
+          array(':field' => $field_name, ':format' => $format)
+        );
+      }
+    }
+    else {
+      tripal_report_error(
+        'tripal_search',
+        TRIPAL_ERROR,
+        'Unable to get value for :field because the schema field was not set.',
+        array(':field' => $field_name)
+      );
+    }
+  }
+
+  return NULL;
+}
+
+/**
+ * Retrieve values for all tokens for an entity property getter function.
+ */
+function tripal_core_get_token_value_for_property($base_table, $field_name, $format, $data, $info) {
+
+  // Determine which tokens were used in the format string
+  if (preg_match_all('/\[[^]]+\]/', $format, $used_tokens)) {
+    $used_tokens = $used_tokens[0];
+
+    // If there are no tokens then return the format as is...
+    if (empty($used_tokens)) {
+      tripal_report_error(
+        'tripal_search',
+        TRIPAL_NOTICE,
+        'Returned static text for :field since there were no tokens in the supplied format: :format',
+        array(':field' => $field_name, ':format' => $format)
+      );
+      return $format;
+    }
+
+    // Get the value of each token.
+    $null_tokens = array();
+    foreach ($used_tokens as $token) {
+      $token_info = array(
+          'name' => $info['label'],
+          'table' => $base_table,
+          'field' => $field_name,
+          'token' => $token,
+          'description' => $info['description'],
+          'location' => chado_node_get_location_from_token($token),
+      );
+
+      $value = chado_get_token_value($token_info, $data, array('supress_errors' => TRUE));
+      if (empty($value)) $null_tokens[] = $token;
+
+      // And sub it in to the format.
+      $format = str_replace($token, $value, $format);
+    }
+
+    // If none of the tokens had values then this node doesn't have this field.
+    // As such we return null so the search api doesn't bother indexing an empty format.
+    if (sizeof($used_tokens) == sizeof($null_tokens)) return NULL;
+  }
+  else {
+    tripal_report_error(
+      'tripal_search',
+      TRIPAL_NOTICE,
+      'Returned static text for :field since there were no tokens of a recognized format in the supplied format: :format',
+      array(':field' => $field_name, ':format' => $format)
+    );
+  }
+
+  return $format;
+}
+
+/**
+ * Implements hook_modules_enabled().
+ *
+ * This hook is called when ANY module is enabled. This allows us to update the
+ * the search api "Default node index" when any Tripal module is enabled thus allowing us
+ * to catch new node types right after they're created.
+ */
+function tripal_core_modules_enabled($modules) {
+  if (module_exists('search_api')) {
+    $index_enabled = db_query('SELECT enabled FROM search_api_index WHERE machine_name=:name', array(':name' => 'default_node_index'))->fetchField();
+    if ($index_enabled) {
+      tripal_search_update_default_index();
+    }
+  }
+}
+
+/**
+ * The Search API provides a default node index which has a number of
+ * node-specific fields enabled by default. We want to ensure our
+ * chado fields are also enabled by default thus making for easier
+ * enabling of Tripal search.
+ *
+ * This function should be called whenever new nodes might have been
+ * added to ensure that their fields are added as well.
+ *
+ * We should only modify the default node index if it has no database service yet.
+ * That way we ensure we don't override user changes!
+ */
+function tripal_search_update_default_index() {
+
+  // First we need the index object for the "Default node index".
+  $index_id = db_query('SELECT id FROM search_api_index WHERE machine_name=:name',
+    array(':name' => 'default_node_index'))->fetchField();
+  if (!$index_id) {
+    // ERROR
+    return FALSE;
+  }
+  $index = search_api_index_load($index_id);
+
+  // Collect all the fields already added to the search index.
+  $changes = array('options' => $index->options);
+
+  // Now we only want to update the index if it's both enabled and has no server indicated.
+  // That way we can be reasonably sure that it was been untouched by admin users.
+  if ($index->enabled == FALSE AND $index->server == NULL) {
+
+    // We need information about all the fields available to nodes before we can
+    // go crazy enabling them... That information is stored as properties of nodes
+    // so we'll grab that.
+    $info = entity_get_property_info('node');
+
+    // Now we want to loop through each node type and add all the properties for the
+    // chado node types.
+    // Assumption #1: We are assuming that all chado node types are prefixed 'chado_'.
+    foreach ($info['bundles'] as $node_type => $details) {
+      if (preg_match('/^chado_/', $node_type)) {
+
+        // Now add each chado fields to the index but only if they are not already added.
+        foreach ($details['properties'] as $field_name => $field_details) {
+          if (!isset($changes['options']['fields'][$field_name])) {
+            $changes['options']['fields'][$field_name]['type'] = ($field_details['type'] == 'varchar') ? 'text' : $field_details['type'];
+
+            // Furthermore if this is a name then we want to add a boost to ensure it carries
+            // more weight in the search results.
+            if (preg_match('/name/',$field_name)) {
+              $changes['options']['fields'][$field_name]['boost'] = '3.0';
+            }
+          }
+        }
+
+      }
+    }
+
+    // We also want to enable highlighting to ensure an excerpt is generated since this
+    // will be used in the default search view distributed with Tripal.
+    if (!isset($index->options['processors']['search_api_highlighting'])) {
+      $changes['options']['processors']['search_api_highlighting'] = array(
+        'status' => 1,
+        'weight' => 35,
+        'settings' => array(
+          'prefix' => '<strong>',
+          'suffix' => '</strong>',
+          'excerpt' => 1,
+          'excerpt_length' => 256,
+          'exclude_fields' => array(),
+          'highlight' => 'always',
+        ),
+      );
+    }
+    else {
+      $changes['options']['processors']['search_api_highlighting']['status'] = 1;
+      $changes['options']['processors']['search_api_highlighting']['settings']['excerpt'] = 1;
+    }
+
+    // Finally we save all of our changes :-).
+    search_api_index_edit($index_id, $changes);
+    drupal_set_message('The Search API "Default Node Index" was updated.');
+  }
+  else {
+    tripal_report_error(
+      'tripal_search',
+      TRIPAL_NOTICE,
+      'The Search API "Default Node Index" was not updated with Tripal Fields. If you would like to enable more Tripal/Chado fields to be indexed, edit the Field Listing for the "Default Node Index" now.'
+    );
+  }
+}
+

+ 1 - 2
tripal_core/tripal_core.info

@@ -11,5 +11,4 @@ scripts[]          = theme/js/tripal.js
 
 dependencies[]     = views
 dependencies[]     = path
-dependencies[]     = search
-dependencies[]     = php
+dependencies[]     = php

+ 124 - 0
tripal_core/tripal_core.module

@@ -22,6 +22,7 @@ require_once 'includes/tripal_core.mviews.inc';
 require_once 'includes/tripal_core.custom_tables.inc';
 require_once 'includes/tripal_core.chado_install.inc';
 require_once 'includes/tripal_core.form_elements.inc';
+require_once 'includes/tripal_core.search.inc';
 
 // Set some global variables.
 tripal_core_set_globals();
@@ -733,3 +734,126 @@ function tripal_core_import_api() {
   module_load_include('inc', 'tripal_core', 'api/tripal_core.tripal_variables.api');
   module_load_include('inc', 'tripal_core', 'api/tripal_core.tripal.api');
 }
+
+/**
+ * Implements hook_block_info().
+ */
+function tripal_core_block_info() {
+
+  $blocks['tripal_search'] = array(
+    'info' => t('Tripal Search Block'),
+    'cache' => DRUPAL_NO_CACHE,
+  );
+
+  return $blocks;
+}
+
+/**
+ * Implements hook_block_view().
+ */
+function tripal_core_block_view($delta = '') {
+  $block = array();
+
+  switch ($delta) {
+    case 'tripal_search':
+      $block['title'] = 'Search';
+
+      $form_render_arr = drupal_get_form('tripal_core_search_block');
+      $block['content'] = array(
+        '#markup' => drupal_render($form_render_arr),
+      );
+      break;
+  }
+
+  return $block;
+}
+
+/**
+ * A simple search box form.
+ */
+function tripal_core_search_block($form, $form_state) {
+
+  $form['wrapper'] = array(
+    '#prefix' => '<div id="search-block-form" class="container-inline">',
+    '#suffix' => '</div>',
+  );
+
+  $form['wrapper']['title'] = array(
+    '#markup' => '<h2 class="element-invisible">Search form</h2>',
+  );
+
+  $form['wrapper']['search_block_form'] = array(
+    '#title' => 'Search',
+    '#title_display' => 'invisible',
+    '#type' => 'textfield',
+    '#size' => 15,
+    '#maxlength' => 128,
+    '#attributes' =>array('placeholder' => t(variable_get('tripal_search_placeholder', 'Keywords')))
+  );
+
+  $form['wrapper']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => 'Search',
+    '#prefix' => '<div class="form-actions form-wrapper" id="edit-actions">',
+    '#suffix' => '</div>'
+  );
+
+  return $form;
+}
+
+/**
+ * Submit for tripal_core_search_block form.
+ */
+function tripal_core_search_block_submit($form, &$form_state) {
+
+  $form_state['redirect'] = array(
+    variable_get('tripal_search_block_url', 'search/data'),
+    array(
+      'query' => array(
+        'keywords' => $form_state['values']['search_block_form']
+      ),
+    ),
+  );
+
+}
+
+/**
+ * Implements hook_block_configure().
+ */
+function tripal_core_block_configure ($delta = '') {
+  $form = array();
+
+  $form['search_url'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Search Page URL',
+    '#description' => 'The URL for the page you would like to redirect to when the user
+        clicks "Search". It is expected that this page will be a view with an exposed
+        filter having a "Filter Identifier" (in "More" fieldset on the edit filter form)
+        of "keywords".',
+    '#default_value' => variable_get('tripal_search_block_url', 'search/data'),
+  );
+
+  $form['search_placeholder'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Placeholder Text',
+    '#description' => 'Change the text that shows up within the search box until the user enters any of their own text.',
+    '#default_value' => variable_get('tripal_search_placeholder', 'Keywords'),
+  );
+
+  return $form;
+}
+
+/**
+ * Implements hook_block_save().
+ */
+function tripal_core_block_save($delta = '', $edit = array()) {
+
+  // We simply want to save this information in a Drupal variable for use in the form submit.
+  if (!empty($edit['search_url'])) {
+    variable_set('tripal_search_block_url', $edit['search_url']);
+  }
+
+  if (!empty($edit['search_placeholder'])) {
+    variable_set('tripal_search_placeholder', $edit['search_placeholder']);
+  }
+}

+ 90 - 2
tripal_core/tripal_core.views_default.inc

@@ -21,6 +21,16 @@ function tripal_core_views_default_views() {
   $view = tripal_core_admin_defaultview_mviews();
   $views[$view->name] = $view;
 
+  // We only want to make this view available if the Search API module is installed
+  // and the "Default Node Index has been enabled.
+  if (module_exists('search_api')) {
+    $index_enabled = db_query('SELECT enabled FROM search_api_index WHERE machine_name=:name', array(':name' => 'default_node_index'))->fetchField();
+    if ($index_enabled) {
+      $view = tripal_core_search_default_node_index();
+      $views[$view->name] = $view;
+    }
+  }
+
   return $views;
 }
 
@@ -317,7 +327,7 @@ function tripal_core_admin_defaultview_custom_tables() {
   $view->core = 7;
   $view->api_version = '3.0';
   $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
-  
+
   /* Display: Master */
   $handler = $view->new_display('default', 'Master', 'default');
   $handler->display->display_options['title'] = 'Custom Tables';
@@ -416,7 +426,7 @@ function tripal_core_admin_defaultview_custom_tables() {
     1 => 0,
     3 => 0,
   );
-  
+
   /* Display: Page */
   $handler = $view->new_display('page', 'Page', 'page');
   $handler->display->display_options['path'] = 'admin/tripal/schema/custom_tables/tables';
@@ -698,3 +708,81 @@ function tripal_core_admin_defaultview_mviews() {
 
   return $view;
 }
+
+/**
+ * Provides a default search view for the Search API "Default Node Index".
+ */
+function tripal_core_search_default_node_index() {
+
+  $view = new view();
+  $view->name = 'search_api_default_node_search';
+  $view->description = 'A default keyword-based search view using the search API "Default node index".';
+  $view->tag = 'search';
+  $view->base_table = 'search_api_index_default_node_index';
+  $view->human_name = 'Search';
+  $view->core = 7;
+  $view->api_version = '3.0';
+  $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+
+  /* Display: Master */
+  $handler = $view->new_display('default', 'Master', 'default');
+  $handler->display->display_options['title'] = 'Search';
+  $handler->display->display_options['use_more_always'] = FALSE;
+  $handler->display->display_options['access']['type'] = 'none';
+  $handler->display->display_options['cache']['type'] = 'none';
+  $handler->display->display_options['query']['type'] = 'views_query';
+  $handler->display->display_options['exposed_form']['type'] = 'input_required';
+  $handler->display->display_options['exposed_form']['options']['submit_button'] = 'Search';
+  $handler->display->display_options['exposed_form']['options']['expose_sort_order'] = FALSE;
+  $handler->display->display_options['exposed_form']['options']['text_input_required'] = '';
+  $handler->display->display_options['exposed_form']['options']['text_input_required_format'] = 'filtered_html';
+  $handler->display->display_options['pager']['type'] = 'full';
+  $handler->display->display_options['pager']['options']['items_per_page'] = '25';
+  $handler->display->display_options['pager']['options']['offset'] = '0';
+  $handler->display->display_options['pager']['options']['id'] = '0';
+  $handler->display->display_options['pager']['options']['quantity'] = '9';
+  $handler->display->display_options['style_plugin'] = 'default';
+  $handler->display->display_options['row_plugin'] = 'fields';
+  /* Field: Content: Rendered Node */
+  $handler->display->display_options['fields']['rendered_entity']['id'] = 'rendered_entity';
+  $handler->display->display_options['fields']['rendered_entity']['table'] = 'views_entity_node';
+  $handler->display->display_options['fields']['rendered_entity']['field'] = 'rendered_entity';
+  $handler->display->display_options['fields']['rendered_entity']['label'] = '';
+  $handler->display->display_options['fields']['rendered_entity']['element_label_colon'] = FALSE;
+  $handler->display->display_options['fields']['rendered_entity']['link_to_entity'] = 1;
+  $handler->display->display_options['fields']['rendered_entity']['display'] = 'view';
+  $handler->display->display_options['fields']['rendered_entity']['view_mode'] = 'teaser';
+  $handler->display->display_options['fields']['rendered_entity']['bypass_access'] = 0;
+  /* Sort criterion: Search: Relevance */
+  $handler->display->display_options['sorts']['search_api_relevance']['id'] = 'search_api_relevance';
+  $handler->display->display_options['sorts']['search_api_relevance']['table'] = 'search_api_index_default_node_index';
+  $handler->display->display_options['sorts']['search_api_relevance']['field'] = 'search_api_relevance';
+  $handler->display->display_options['sorts']['search_api_relevance']['order'] = 'DESC';
+  /* Filter criterion: Search: Fulltext search */
+  $handler->display->display_options['filters']['search_api_views_fulltext']['id'] = 'search_api_views_fulltext';
+  $handler->display->display_options['filters']['search_api_views_fulltext']['table'] = 'search_api_index_default_node_index';
+  $handler->display->display_options['filters']['search_api_views_fulltext']['field'] = 'search_api_views_fulltext';
+  $handler->display->display_options['filters']['search_api_views_fulltext']['operator'] = 'OR';
+  $handler->display->display_options['filters']['search_api_views_fulltext']['exposed'] = TRUE;
+  $handler->display->display_options['filters']['search_api_views_fulltext']['expose']['operator_id'] = 'search_api_views_fulltext_op';
+  $handler->display->display_options['filters']['search_api_views_fulltext']['expose']['label'] = 'Keywords';
+  $handler->display->display_options['filters']['search_api_views_fulltext']['expose']['operator'] = 'search_api_views_fulltext_op';
+  $handler->display->display_options['filters']['search_api_views_fulltext']['expose']['identifier'] = 'keywords';
+  $handler->display->display_options['filters']['search_api_views_fulltext']['expose']['remember_roles'] = array(
+    2 => '2',
+    1 => 0,
+    3 => 0,
+  );
+
+  /* Display: Page */
+  $handler = $view->new_display('page', 'Page', 'page');
+  $handler->display->display_options['path'] = 'chado';
+  $handler->display->display_options['menu']['type'] = 'normal';
+  $handler->display->display_options['menu']['title'] = 'Search';
+  $handler->display->display_options['menu']['description'] = 'General keyword search of all content.';
+  $handler->display->display_options['menu']['weight'] = '0';
+  $handler->display->display_options['menu']['context'] = 0;
+  $handler->display->display_options['menu']['context_only_inline'] = 0;
+
+  return $view;
+}

+ 56 - 12
tripal_cv/api/tripal_cv.api.inc

@@ -524,9 +524,9 @@ function tripal_insert_cvterm($term, $options = array()) {
   }
 
   // This SQL statement will be used a lot to find a cvterm so just set it
-  // here for easy reference below.  Because CV terms can change their names
-  // but accessions don't change, the following SQL finds cvterms based on
-  // their accession rather than the name.
+  // here for easy reference below.  The following SQL tries to cover both the following:
+  // 1) The cvterm name may have changed but the accession remains constant
+  // 2) The cvterm name remains constant but the daccession/db may have changed (rare).
   $cvtermsql = "
     SELECT CVT.name, CVT.cvterm_id, CV.cv_id, CV.name as cvname,
       DB.name as dbname, DB.db_id, DBX.accession
@@ -534,7 +534,7 @@ function tripal_insert_cvterm($term, $options = array()) {
       INNER JOIN {dbxref} DBX on CVT.dbxref_id = DBX.dbxref_id
       INNER JOIN {db} DB on DBX.db_id = DB.db_id
       INNER JOIN {cv} CV on CV.cv_id = CVT.cv_id
-    WHERE DBX.accession = :accession and DB.name = :name
+    WHERE (DBX.accession = :accession and DB.name = :dbname) OR (CVT.name = :term and CV.name = :cvname)
   ";
 
   // Add the database. The function will just return the DB object if the
@@ -566,6 +566,15 @@ function tripal_insert_cvterm($term, $options = array()) {
     $values = array('dbxref_id' => $cvterm->dbxref_id);
     $result = chado_select_record('dbxref', array('*'), $values);
     $dbxref = $result[0];
+    if (!$dbxref) {
+      tripal_report_error(
+        'tripal_cv',
+        TRIPAL_ERROR,
+        'Unable to access the dbxref record for the :term cvterm. Term Record: !record',
+        array(':term' => $name, '!record' => print_r($cvterm, TRUE))
+      );
+      return FALSE;
+    }
 
     // Get the db.
     $values = array('db_id' => $dbxref->db_id);
@@ -648,7 +657,7 @@ function tripal_insert_cvterm($term, $options = array()) {
         }
       }
       // get the original cvterm with the same name and return that.
-      $result = chado_query($cvtermsql, array(':accession' => $dbxref->accession, ':name' => $dbname));
+      $result = chado_query($cvtermsql, array(':accession' => $dbxref->accession, ':dbname' => $dbname, ':term' => $name, ':cvname' => $cvname));
       $cvterm = $result->fetchObject();
       return $cvterm;
     }
@@ -657,10 +666,7 @@ function tripal_insert_cvterm($term, $options = array()) {
     // We can now perform and updated if we need to.
   }
 
-  // Get the CVterm record.  If it doesn't exist then create it.
-  $result = chado_query($cvtermsql, array(':accession' => $accession, ':name' => $dbname));
-  $cvterm = $result->fetchObject();
-  if (!$cvterm) {
+  if (!$result) {
 
     // check to see if the dbxref exists if not, add it.
     $dbxref =  tripal_insert_dbxref(array(
@@ -705,11 +711,13 @@ function tripal_insert_cvterm($term, $options = array()) {
       tripal_report_error('tripal_cv', TRIPAL_WARNING, "The dbxref already exists for another cvterm record: $name (cv: " . $cvname . " db: $dbname)", NULL);
       return 0;
     }
-    $result = chado_query($cvtermsql, array(':accession' => $accession, ':name' => $dbname));
+    $result = chado_query($cvtermsql, array(':accession' => $dbxref->accession, ':dbname' => $dbname, ':term' => $name, ':cvname' => $cvname));
     $cvterm = $result->fetchObject();
   }
   // Update the cvterm.
   elseif ($update) {
+
+    // First, basic update of the term.
     $match = array('cvterm_id' => $cvterm->cvterm_id);
     $upd_values = array(
       'name'                => $name,
@@ -723,7 +731,43 @@ function tripal_insert_cvterm($term, $options = array()) {
       tripal_report_error('tripal_cv', TRIPAL_WARNING, "Failed to update the term: $name", NULL);
       return 0;
     }
-    $result = chado_query($cvtermsql, array(':accession' => $accession, ':name' => $dbname));
+
+    // Second, check that the dbxref has not changed and if it has then update it.
+    $checksql = "
+      SELECT cvterm_id
+      FROM {cvterm} CVT
+        INNER JOIN {dbxref} DBX on CVT.dbxref_id = DBX.dbxref_id
+        INNER JOIN {db} DB on DBX.db_id = DB.db_id
+        INNER JOIN {cv} CV on CV.cv_id = CVT.cv_id
+      WHERE DBX.accession = :accession and DB.name = :dbname and CVT.name = :term and CV.name = :cvname
+    ";
+    $check = chado_query($checksql, array(':accession' => $dbxref->accession, ':dbname' => $dbname, ':term' => $name, ':cvname' => $cvname))->fetchObject();
+    if (!$check) {
+
+      // check to see if the dbxref exists if not, add it.
+      $dbxref =  tripal_insert_dbxref(array(
+        'db_id' => $db->db_id,
+        'accession' => $accession
+      ));
+      if (!$dbxref) {
+        tripal_report_error('tripal_cv', TRIPAL_WARNING, "Failed to find or insert the dbxref record for cvterm, " .
+          "$name (id: $accession), for database $dbname", NULL);
+        return 0;
+      }
+
+      $match = array('cvterm_id' => $cvterm->cvterm_id);
+      $upd_values = array(
+        'dbxref_id' => $dbxref->dbxref_id,
+      );
+      $success = chado_update_record('cvterm', $match, $upd_values);
+      if (!$success) {
+        tripal_report_error('tripal_cv', TRIPAL_WARNING, "Failed to update the term $name with new accession $db:$accession", NULL);
+        return 0;
+      }
+    }
+
+    // Finally grab the updated details.
+    $result = chado_query($cvtermsql, array(':accession' => $dbxref->accession, ':dbname' => $dbname, ':term' => $name, ':cvname' => $cvname));
     $cvterm = $result->fetchObject();
   }
   else {
@@ -1111,4 +1155,4 @@ function tripal_get_cvterm_default_select_options($table, $field, $field_desc) {
   }
 
   return $options;
-}
+}

+ 1 - 5
tripal_cv/includes/tripal_cv.cvterm_form.inc

@@ -37,11 +37,7 @@ function tripal_cv_cvterm_edit_form($form, &$form_state) {
     $cv_id = $form_state['build_info']['args'][0];
     $cvterm_id = $form_state['build_info']['args'][1];
     if ($form_state['build_info']['args'][1]) {
-      $result = db_select('chado.cvterm','c')
-        ->fields('c', array('name'))
-        ->condition('c.cvterm_id',$cvterm_id)
-        ->execute();
-      $cvterm_name = $result->fetchObject()->name;
+      $cvterm_name = chado_query('SELECT name FROM {cvterm} WHERE cvterm_id=:id', array(':id' => $cvterm_id))->fetchField();
       $step = 1;
     }
   }

+ 1 - 1
tripal_cv/includes/tripal_cv.obo_loader.inc

@@ -1433,7 +1433,7 @@ function tripal_cv_obo_add_dbxref($db_id, $accession, $version='', $description=
       tripal_cv_obo_quiterror("Failed to insert the dbxref record $accession");
       return FALSE;
     }
-    $result = chado_select_record('dbxref', array('dbxref_id'), $values, $options);
+    $result = chado_select_record('dbxref', array('dbxref_id'), $values);
   }
   return $result[0];
 }

+ 5 - 5
tripal_cv/tripal_cv.install

@@ -73,9 +73,9 @@ function tripal_cv_install() {
 function tripal_cv_uninstall() {
 
   // drop the tripal_obo_temp table
-  if (db_table_exists('chado.tripal_obo_temp')) {
-    $sql = "DROP TABLE chado.tripal_obo_temp";
-    db_query($sql);
+  if (chado_table_exists('tripal_obo_temp')) {
+    $sql = "DROP TABLE {tripal_obo_temp}";
+    chado_query($sql);
   }
 }
 
@@ -90,7 +90,7 @@ function tripal_cv_create_tripal_obo_temp() {
   // do not want to use the Tripal Custom Table API because we don't want it to appear in the
   // list of custom tables.  It needs to be available for the Tripal Chado API so we create it
   // here and then define it in the tripal_cv/api/tripal_cv.schema.api.inc
-  if (!db_table_exists('chado.tripal_obo_temp')) {
+  if (!chado_table_exists('tripal_obo_temp')) {
     $sql = "
       CREATE TABLE {tripal_obo_temp} (
         id character varying(255) NOT NULL,
@@ -334,4 +334,4 @@ function tripal_cv_update_dependencies() {
   $dependencies = array();
 
   return $dependencies;
-}
+}

+ 1 - 1
tripal_cv/tripal_cv.module

@@ -154,7 +154,7 @@ function tripal_cv_menu() {
     'type' => MENU_CALLBACK,
   );
   $items['admin/tripal/chado/tripal_cv/cvterm/auto_name/%/%'] = array(
-    'page callback' => 'tripal_cv_cvterm_name_autocomplete',
+    'page callback' => 'tripal_autocomplete_cvterm',
     'page arguments' => array(6, 7),
     'access arguments' => array('administer controlled vocabularies'),
     'type' => MENU_CALLBACK,

+ 30 - 30
tripal_featuremap/tripal_featuremap.install

@@ -548,73 +548,73 @@ function tripal_featuremap_update_7201() {
     $fkey_exists = db_query('SELECT TRUE FROM pg_constraint WHERE conname = :constraint', array(':constraint' => 'featuremapprop_type_id_fkey'))->fetchField();
     if ($fkey_exists) {
       // featuremapprop table
-      db_query('
-        ALTER TABLE chado.featuremapprop
+      chado_query('
+        ALTER TABLE {featuremapprop}
         DROP CONSTRAINT featuremapprop_type_id_fkey CASCADE
       ');
-      db_query('
-        ALTER TABLE chado.featuremapprop
+      chado_query('
+        ALTER TABLE {featuremapprop}
         DROP CONSTRAINT featuremapprop_featuremap_id_fkey CASCADE
       ');
     }
-    db_query('
-      ALTER TABLE chado.featuremapprop
+    chado_query('
+      ALTER TABLE {featuremapprop}
       ADD CONSTRAINT featuremapprop_type_id_fkey
-      FOREIGN KEY (type_id) REFERENCES chado.cvterm (cvterm_id)
+      FOREIGN KEY (type_id) REFERENCES {cvterm} (cvterm_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
-    db_query('
-      ALTER TABLE chado.featuremapprop
+    chado_query('
+      ALTER TABLE {featuremapprop}
       ADD CONSTRAINT featuremapprop_featuremap_id_fkey
-      FOREIGN KEY (featuremap_id) REFERENCES chado.featuremap (featuremap_id)
+      FOREIGN KEY (featuremap_id) REFERENCES {featuremap} (featuremap_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
 
     // featuremap_dbref table
     if ($fkey_exists) {
-      db_query('
-        ALTER TABLE chado.featuremap_dbxref
+      chado_query('
+        ALTER TABLE {featuremap_dbxref}
         DROP CONSTRAINT featuremap_dbxref_dbxref_id_fkey CASCADE
       ');
-      db_query('
-        ALTER TABLE chado.featuremap_dbxref
+      chado_query('
+        ALTER TABLE {featuremap_dbxref}
         DROP CONSTRAINT featuremap_dbxref_featuremap_id_fkey CASCADE
       ');
     }
-    db_query('
-      ALTER TABLE chado.featuremap_dbxref
+    chado_query('
+      ALTER TABLE {featuremap_dbxref}
       ADD CONSTRAINT featuremap_dbxref_dbxref_id_fkey
-      FOREIGN KEY (dbxref_id) REFERENCES chado.dbxref (dbxref_id)
+      FOREIGN KEY (dbxref_id) REFERENCES {dbxref} (dbxref_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
-    db_query('
-      ALTER TABLE chado.featuremap_dbxref
+    chado_query('
+      ALTER TABLE {featuremap_dbxref}
       ADD CONSTRAINT featuremap_dbxref_featuremap_id_fkey
-      FOREIGN KEY (featuremap_id) REFERENCES chado.featuremap (featuremap_id)
+      FOREIGN KEY (featuremap_id) REFERENCES {featuremap} (featuremap_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
 
     // featureposprop
     if ($fkey_exists) {
-      db_query('
-        ALTER TABLE chado.featureposprop
+      chado_query('
+        ALTER TABLE {featureposprop}
         DROP CONSTRAINT featureposprop_type_id_fkey CASCADE
       ');
-      db_query('
-        ALTER TABLE chado.featureposprop
+      chado_query('
+        ALTER TABLE {featureposprop}
         DROP CONSTRAINT featureposprop_featurepos_id_fkey CASCADE
       ');
     }
-    db_query('
-      ALTER TABLE chado.featureposprop
+    chado_query('
+      ALTER TABLE {featureposprop}
       ADD CONSTRAINT featureposprop_type_id_fkey
-      FOREIGN KEY (type_id) REFERENCES chado.cvterm (cvterm_id)
+      FOREIGN KEY (type_id) REFERENCES {cvterm} (cvterm_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
-    db_query('
-      ALTER TABLE chado.featureposprop
+    chado_query('
+      ALTER TABLE {featureposprop}
       ADD CONSTRAINT featureposprop_featurepos_id_fkey
-      FOREIGN KEY (featurepos_id) REFERENCES chado.featurepos (featurepos_id)
+      FOREIGN KEY (featurepos_id) REFERENCES {featurepos} (featurepos_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
   }

+ 42 - 81
tripal_library/tripal_library.install

@@ -269,15 +269,15 @@ function tripal_library_update_7200() {
   // site upgrade when the tripal_core module is disabled.
   module_load_include('module', 'tripal_core', 'tripal_core');
   tripal_core_import_api();
+  module_load_include('inc', 'tripal_cv', 'api/tripal_cv.api');
 
   // the library types were formerly in a vocabulary named 'tripal_library_types'.
-  // rename that to just be 'library_type'. We cannot use the Tripal API calls
-  // because during upgrade the tripal_core should also be disabled
+  // rename that to just be 'library_type'.
   try {
-    $check = db_query("SELECT cv_id FROM chado.cv WHERE name = 'library_type'")->fetchObject();
+    $check = chado_query("SELECT cv_id FROM {cv} WHERE name = 'library_type'")->fetchObject();
     if (!$check->cv_id) {
-      $sql = "UPDATE chado.cv SET name = 'library_type' WHERE name = 'tripal_library_types'";
-      db_query($sql);
+      $sql = "UPDATE {cv} SET name = 'library_type' WHERE name = 'tripal_library_types'";
+      chado_query($sql);
     }
   }
   catch (\PDOException $e) {
@@ -287,13 +287,18 @@ function tripal_library_update_7200() {
 
   // add the library_property CV
   try {
-    $check = db_query("SELECT cv_id FROM chado.cv WHERE name = 'library_property'")->fetchObject();
-    if (!$check->cv_id) {
-      $sql = "INSERT INTO chado.cv (name, definition) VALUES (
-        'library_property',
-        'Contains properties for libraries.')
-      ";
-      db_query($sql);
+    $cv = tripal_insert_cv(
+      'library_property',
+      'Contains properties for libraries.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // Set as Default CV for library properties.
+      $is_set = tripal_get_default_cv('libraryprop', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('libraryprop','type_id', 'library_property', $cv_id);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -303,13 +308,20 @@ function tripal_library_update_7200() {
 
   // add the library_type CV
   try {
-    $check = db_query("SELECT cv_id FROM chado.cv WHERE name = 'library_type'")->fetchObject();
-    if (!$check->cv_id) {
-      $sql = "INSERT INTO chado.cv (name, definition) VALUES (
-        'library_type',
-        'Contains terms for types of libraries (e.g. BAC, cDNA, FOSMID, etc).')
-      ";
-      db_query($sql);
+    // Note: tripal_insert_cv will only insert it if doesn't already exist
+    // so this doesn't conflict with the update above.
+    $cv = tripal_insert_cv(
+      'library_type',
+      'Contains terms for types of libraries (e.g. BAC, cDNA, FOSMID, etc).'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // Set as Default CV for library types.
+      $is_set = tripal_get_default_cv('library', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('library','type_id', 'library_type', $cv_id);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -321,19 +333,17 @@ function tripal_library_update_7200() {
   // 'tripal' CV.  It should be stored in the new library_property CV that
   // is added by this module for Tripal 2.0 and Drupal 7.  So, we need to
   // reset the CV ID for that term and rename the term to 'Library Description'
-  // We cannot use the Tripal API calls in the 7000 update
-  // because during upgrade the tripal_core should also be disabled
-  $sql = "
-    UPDATE chado.cvterm
-    SET
-      name = 'Library Description',
-      cv_id = (SELECT cv_id FROM chado.cv WHERE name = 'library_property')
-    WHERE
-      name = 'library_description' AND
-      cv_id = (SELECT cv_id FROM chado.cv WHERE name = 'tripal')
-  ";
   try {
-    db_query($sql);
+    $sql = "
+      UPDATE {cvterm}
+      SET
+        name = 'Library Description',
+        cv_id = (SELECT cv_id FROM {cv} WHERE name = 'library_property')
+      WHERE
+        name = 'library_description' AND
+        cv_id = (SELECT cv_id FROM {cv} WHERE name = 'tripal')
+    ";
+    chado_query($sql);
   }
   catch (\PDOException $e) {
     $error = $e->getMessage();
@@ -377,55 +387,6 @@ function tripal_library_update_7200() {
       throw new DrupalUpdateException('Could not move library taxonomy terms: '. $error);
     }
   }
-
-  // set the default vocabularies
-  // library_type
-  try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'library_type'")->fetchField();
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'library')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'library',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-        ))
-        ->execute();
-    }
-  }
-  catch (\PDOException $e) {
-    $error = $e->getMessage();
-    throw new DrupalUpdateException('Failed to set library_type vocabulary as default: '. $error);
-  }
-  // library_property
-  try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'library_property'")->fetchField();
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'libraryprop')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'libraryprop',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-        ))
-        ->execute();
-    }
-  }
-  catch (\PDOException $e) {
-    $error = $e->getMessage();
-    throw new DrupalUpdateException('Failed to set the library_property vocabulary as default: '. $error);
-  }
-
 }
 
 /**
@@ -483,4 +444,4 @@ function tripal_library_update_7201() {
       ->condition('name', $view_name)
       ->execute();
   }
-}
+}

+ 35 - 58
tripal_project/tripal_project.install

@@ -143,34 +143,24 @@ function tripal_project_update_7200() {
   // site upgrade when the tripal_core module is disabled.
   module_load_include('module', 'tripal_core', 'tripal_core');
   tripal_core_import_api();
+  module_load_include('inc', 'tripal_cv', 'api/tripal_cv.api');
 
-  // add the project_property CV
+  // Add the project_property CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'project_property'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-        ->fields(array(
-          'name' => 'project_property',
-          'definition' => 'Contains properties for projects.'
-        ))
-        ->execute();
-    }
-    // use the new project_property CV we just added
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'projectprop')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-        'table_name' => 'projectprop',
-        'field_name' => 'type_id',
-        'cv_id' => $cv_id
-        ))
-        ->execute();
+    // First we add the cv.
+    // Notice that tripal_insert_cv() will only add it if it doesn't exist already.
+    $cv = tripal_insert_cv(
+      'project_property',
+      'Contains properties for projects'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // Set as Default CV for contact types.
+      $is_set = tripal_get_default_cv('projectprop', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('projectprop','type_id', 'project_property', $cv_id);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -180,31 +170,20 @@ function tripal_project_update_7200() {
 
   // add the project_relationship CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'project_relationship'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-      ->fields(array(
-        'name' => 'project_relationship',
-        'definition' => 'Contains types of relationships between projects.'
-      ))
-      ->execute();
-    }
-    // use the new project_property CV we just added
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'project_relationship')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'project_relationship',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-        ))
-        ->execute();
+    // First we add the cv.
+    // Notice that tripal_insert_cv() will only add it if it doesn't exist already.
+    $cv = tripal_insert_cv(
+      'project_relationship',
+      'Contains types of relationships between projects.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // Set as Default CV for contact types.
+      $is_set = tripal_get_default_cv('project_relationship', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('project_relationship','type_id', 'project_relationship', $cv_id);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -216,19 +195,17 @@ function tripal_project_update_7200() {
   // 'tripal' CV.  It should be stored in the new project_property CV that
   // is added by this module for Tripal 2.0 and Drupal 7.  So, we need to
   // reset the CV ID for that term and rename the term to 'Project Description'
-  // We cannot use the Tripal API calls'because during upgrade the tripal_core
-  // should also be disabled
   $sql = "
-    UPDATE chado.cvterm CVT
+    UPDATE {cvterm} CVT
     SET
       name = 'Project Description',
-      cv_id = (SELECT cv_id FROM chado.cv WHERE name = 'project_property')
+      cv_id = (SELECT cv_id FROM {cv} WHERE name = 'project_property')
     WHERE
       name = 'project_description' AND
-      cv_id = (SELECT cv_id FROM chado.cv WHERE name = 'tripal')
+      cv_id = (SELECT cv_id FROM {cv} WHERE name = 'tripal')
   ";
   try {
-    db_query($sql);
+    chado_query($sql);
   }
   catch (\PDOException $e) {
     $error = $e->getMessage();
@@ -254,4 +231,4 @@ function tripal_project_update_dependencies() {
   );
 
   return $dependencies;
-}
+}

+ 51 - 97
tripal_pub/tripal_pub.install

@@ -285,51 +285,30 @@ function tripal_pub_update_7200() {
   // site upgrade when the tripal_core module is disabled.
   module_load_include('module', 'tripal_core', 'tripal_core');
   tripal_core_import_api();
+  module_load_include('inc', 'tripal_cv', 'api/tripal_cv.api');
 
   // add the tripal_pub CV and set it to be the default for pub types and pub properties
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'tripal_pub'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-        ->fields(array(
-          'name' => 'tripal_pub',
-          'definition' => 'A heirarchical set of terms for describing a publication. It is intended to be used as the default vocabularies in Tripal for publication types and contact properties.'
-        ))
-        ->execute();
-    }
-    // use the new pub_property CV we just added
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'pub')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'pub',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-        ))
-        ->execute();
-    }
-
-    // use the new pub_property CV we just added
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'pubprop')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'pubprop',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-        ))
-        ->execute();
+    // First we add the cv.
+    // Notice that tripal_insert_cv() will only add it if it doesn't exist already.
+    $cv = tripal_insert_cv(
+      'tripal_pub',
+      'A heirarchical set of terms for describing a publication. It is intended to be used as the default vocabularies in Tripal for publication types and contact properties.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // Set as Default CV for pub types.
+      $is_set = tripal_get_default_cv('pub', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('pub','type_id', 'tripal_pub', $cv_id);
+      }
+
+      // Set as Default CV for pub properties.
+      $is_set = tripal_get_default_cv('pub', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('pubprop','type_id', 'tripal_pub', $cv_id);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -339,16 +318,10 @@ function tripal_pub_update_7200() {
 
   // add the pub_property CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'pub_property'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-        ->fields(array(
-          'name' => 'pub_property',
-          'definition' => 'Contains properties for publications. This can be used if the tripal_pub vocabulary (which is default for publications in Tripal) is not desired.'
-        ))
-        ->execute();
-    }
+    tripal_insert_cv(
+      'pub_property',
+      'Contains properties for publications. This can be used if the tripal_pub vocabulary (which is default for publications in Tripal) is not desired.'
+    );
   }
   catch (\PDOException $e) {
     $error = $e->getMessage();
@@ -357,16 +330,10 @@ function tripal_pub_update_7200() {
 
   // add the pub_type CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'pub_type'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-      ->fields(array(
-        'name' => 'pub_type',
-        'definition' => 'Contains types of publications. This can be used if the tripal_pub vocabulary (which is default for publications in Tripal) is not desired.'
-      ))
-      ->execute();
-    }
+    $cv = tripal_insert_cv(
+      'pub_type',
+      'Contains types of publications. This can be used if the tripal_pub vocabulary (which is default for publications in Tripal) is not desired.'
+    );
   }
   catch (\PDOException $e) {
     $error = $e->getMessage();
@@ -375,31 +342,18 @@ function tripal_pub_update_7200() {
 
   // add the pub_relationship CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'pub_relationship'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-      ->fields(array(
-        'name' => 'pub_relationship',
-        'definition' => 'Contains types of relationships between publications.'
-      ))
-      ->execute();
-    }
-    // use the new pub_property CV we just added
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'pub_relationship')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'pub_relationship',
-          'field_name' => 'type_id',
-          'cv_id' => $cv_id
-        ))
-        ->execute();
+    $cv = tripal_insert_cv(
+      'pub_relationship',
+      'Contains types of relationships between publications.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // Set as Default CV for pub relationships.
+      $is_set = tripal_get_default_cv('pub_relationship', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('pub_relationship','type_id', 'pub_relationship', $cv_id);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -444,25 +398,25 @@ function tripal_pub_update_7201() {
   try {
     $fkey_exists = db_query('SELECT TRUE FROM pg_constraint WHERE conname = :constraint', array(':constraint' => 'pubauthor_contact_pubauthor_id_fkey'))->fetchField();
     if ($fkey_exists) {
-      db_query('
-        ALTER TABLE chado.pubauthor_contact
+      chado_query('
+        ALTER TABLE {pubauthor_contact}
         DROP CONSTRAINT pubauthor_contact_pubauthor_id_fkey CASCADE
       ');
-      db_query('
-        ALTER TABLE chado.pubauthor_contact
+      chado_query('
+        ALTER TABLE {pubauthor_contact}
         DROP CONSTRAINT pubauthor_contact_contact_id_fkey CASCADE
       ');
     }
-    db_query('
-      ALTER TABLE chado.pubauthor_contact
+    chado_query('
+      ALTER TABLE {pubauthor_contact}
       ADD CONSTRAINT pubauthor_contact_pubauthor_id_fkey
-      FOREIGN KEY (pubauthor_id) REFERENCES chado.pubauthor (pubauthor_id)
+      FOREIGN KEY (pubauthor_id) REFERENCES {pubauthor} (pubauthor_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
-    db_query('
-      ALTER TABLE chado.pubauthor_contact
+    chado_query('
+      ALTER TABLE {pubauthor_contact}
       ADD CONSTRAINT pubauthor_contact_contact_id_fkey
-      FOREIGN KEY (contact_id) REFERENCES chado.contact (contact_id)
+      FOREIGN KEY (contact_id) REFERENCES {contact} (contact_id)
       ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
     ');
   }

+ 56 - 82
tripal_stock/tripal_stock.install

@@ -217,36 +217,28 @@ function tripal_stock_update_7200() {
   // site upgrade when the tripal_core module is disabled.
   module_load_include('module', 'tripal_core', 'tripal_core');
   tripal_core_import_api();
+  module_load_include('inc', 'tripal_cv', 'api/tripal_cv.api');
 
   // add the stock_relationshp CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'stock_relationship'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-        ->fields(array(
-          'name' => 'stock_relationship',
-          'definition' => 'Contains types of relationships between stocks.'
-        ))
-        ->execute();
-    }
-    // for backwards compatibility, get the previously set stock relationship CV, otherwise
-    // use the new stock_relationship CV we just added
-    $default_stockrel_cv = variable_get('chado_stock_relationship_cv', $cv_id);
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'stock_relationship')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-          'table_name' => 'stock_relationship',
-          'field_name' => 'type_id',
-          'cv_id' => $default_stockrel_cv
-        ))
-        ->execute();
+    // First we add the cv.
+    // Notice that tripal_insert_cv() will only add it if it doesn't exist already.
+    $cv = tripal_insert_cv(
+      'stock_relationship',
+      'Contains types of relationships between stocks.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // for backwards compatibility, get the previously set stock relationship CV, otherwise
+      // use the new stock_relationship CV we just added
+      $default_stockrel_cv = variable_get('chado_stock_relationship_cv', $cv_id);
+
+      // Set as Default CV for stock relationship types.
+      $is_set = tripal_get_default_cv('stock_relationship', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('stock_relationship','type_id', 'stock_relationship', $default_stockrel_cv);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -256,33 +248,24 @@ function tripal_stock_update_7200() {
 
   // add the stock_property CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'stock_property'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-        ->fields(array(
-          'name' => 'stock_property',
-          'definition' => 'Contains properties for stocks.'
-        ))
-        ->execute();
-    }
-    // for backwards compatibility, get the previously set stock property CV, otherwise
-    // use the new stock_property CV we just added
-    $default_stockprop_cv = variable_get('chado_stock_prop_types_cv', $cv_id);
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'stockprop')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-        'table_name' => 'stockprop',
-        'field_name' => 'type_id',
-        'cv_id' => $default_stockprop_cv
-        ))
-        ->execute();
+    // First we add the cv.
+    // Notice that tripal_insert_cv() will only add it if it doesn't exist already.
+    $cv = tripal_insert_cv(
+      'stock_property',
+      'Contains properties for stocks.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // for backwards compatibility, get the previously set stock property CV, otherwise
+      // use the new stock_property CV we just added
+      $default_stockprop_cv = variable_get('chado_stock_prop_types_cv', $cv_id);
+
+      // Set as Default CV for stock properties.
+      $is_set = tripal_get_default_cv('stockprop', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('stockprop','type_id', 'stock_property', $default_stockprop_cv);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -293,33 +276,24 @@ function tripal_stock_update_7200() {
 
   // add the stock_type CV
   try {
-    $cv_id = db_query("SELECT cv_id FROM chado.cv WHERE name = 'stock_type'")->fetchField();
-    if (!$cv_id) {
-      // add the vocabulary
-      $cv_id = db_insert('chado.cv')
-      ->fields(array(
-        'name' => 'stock_type',
-        'definition' => 'Contains a list of types for stocks.'
-      ))
-      ->execute();
-    }
-    // for backwards compatibility, get the previously set stock types CV, otherwise
-    // use the new stock_type CV we just added
-    $default_stocktype_cv = variable_get('chado_stock_types_cv', $cv_id);
-    $cdi = db_select('tripal_cv_defaults', 't')
-      ->fields('t', array('cv_default_id'))
-      ->condition('table_name', 'stock')
-      ->condition('field_name', 'type_id')
-      ->execute()
-      ->fetchField();
-    if (!$cdi) {
-      db_insert('tripal_cv_defaults')
-        ->fields(array(
-        'table_name' => 'stock',
-        'field_name' => 'type_id',
-        'cv_id' => $default_stocktype_cv
-        ))
-        ->execute();
+    // First we add the cv.
+    // Notice that tripal_insert_cv() will only add it if it doesn't exist already.
+    $cv = tripal_insert_cv(
+      'stock_type',
+      'Contains a list of types for stocks.'
+    );
+    if ($cv) {
+      $cv_id = $cv->cv_id;
+
+      // for backwards compatibility, get the previously set stock types CV, otherwise
+      // use the new stock_type CV we just added
+      $default_stocktype_cv = variable_get('chado_stock_types_cv', $cv_id);
+
+      // Set as Default CV for stock types.
+      $is_set = tripal_get_default_cv('stock', 'type_id');
+      if (!$is_set) {
+        tripal_set_default_cv('stock','type_id', 'stock_type', $default_stocktype_cv);
+      }
     }
   }
   catch (\PDOException $e) {
@@ -360,4 +334,4 @@ function tripal_stock_update_dependencies() {
   );
 
   return $dependencies;
-}
+}

+ 6 - 3
tripal_views/tripal_views.views.inc

@@ -117,6 +117,9 @@ function tripal_views_views_data() {
   // Manually integrate the drupal.tripal_views* tables
   $data = tripal_views_views_data_tripal_views_tables($data);
 
+  // Determine the name of the chado schema
+  $chado_schema = tripal_get_schema_name('chado');
+
   // MAKE SURE ALL CHADO TABLES ARE INTEGRATED
   tripal_views_integrate_all_chado_tables();
 
@@ -239,7 +242,7 @@ function tripal_views_views_data() {
         'group' => "$tvi_row->name",
         'title' => "$tvi_row->name",
         'help'  => $tvi_row->comment,
-        'search_path' => 'chado'
+        'search_path' => $chado_schema
       );
     }
     else {
@@ -247,7 +250,7 @@ function tripal_views_views_data() {
         'group' => "$tvi_row->name",
         'title' => "$tvi_row->name",
         'help'  => $tvi_row->comment,
-        'search_path' => 'chado'
+        'search_path' => $chado_schema
       );
     }
 
@@ -663,4 +666,4 @@ function tripal_views_views_data_alter(&$data) {
  */
 function tripal_views_views_pre_view(&$view, &$display_id, &$args) {
   $_GET = array_merge($_GET, $_POST);
-}
+}