Browse Source

Merge pull request #314 from tripal/issue253

Issue253
Stephen Ficklin 7 years ago
parent
commit
02b4851755

+ 3 - 6
tripal/tripal.drush.inc

@@ -372,12 +372,9 @@ function drush_tripal_trp_set_permissions() {
 
   drush_tripal_set_user($username);
   $permissions = array();
-  $bundles =
-  db_select('tripal_bundle', 'TB')
-    ->fields('TB', array('name'))
-    ->execute()
-    ->fetchAll();
-  print_r($bundles);
+    
+  $bundles = tripal_get_content_types();
+
   foreach ($bundles as $bundles => $bundle) {
     array_push($permissions, ' view ' . $bundle->name, ' create ' . $bundle->name,
       ' edit ' . $bundle->name, ' delete ' . $bundle->name);

+ 56 - 38
tripal_chado/api/modules/tripal_chado.cv.api.inc

@@ -387,7 +387,8 @@ function tripal_update_cvtermpath($cv_id, $job_id = NULL){
 
     // Iterate through each root level term.
     $record = $result->fetchAll();
-    $roots = array();
+    $roots = [];
+
     foreach ($record as $item){
       tripal_update_cvtermpath_root_loop($item->cvterm_id, $item->cv_id, $roots);
     }
@@ -416,16 +417,24 @@ function tripal_update_cvtermpath($cv_id, $job_id = NULL){
  * @ingroup tripal_chado_cv_api
  */
 function tripal_update_cvtermpath_root_loop($rootid, $cvid, &$roots) {
-
   // Get's the cvterm record for this "root".
-  $ttype = db_select('cvterm', 'cv')
-          ->fields('cv', array('cvterm_id'));
-  $db_or = db_or();
-  $db_or->condition('cv.name', "isa", '=');
-  $db_or->condition('cv.name', "is_a", '=');
-  $ttype->condition($db_or);
-  $result = $ttype->execute()->fetchObject();
+  // $ttype = db_select('cvterm', 'cv')
+  //         ->fields('cv', array('cvterm_id'));
+  // $db_or = db_or();
+  // $db_or->condition('cv.name', "isa", '=');
+  // $db_or->condition('cv.name', "is_a", '=');
+  // $ttype->condition($db_or);
+  $ttype = db_query(
+    'SELECT cv.cvterm_id 
+    FROM cvterm cv
+    WHERE cv.name = :isa 
+          OR cv.name = :is_a
+    '
+    ,
+    array(':isa' => "isa", ':is_a' => "is_a")
+  );
 
+  $result = $ttype->fetchObject();
   $term_id = $rootid . '|' . $rootid . '|' . $cvid . '|' . $result->cvterm_id;
   // If the child_id matches any other id in the array then we've hit a loop.
   foreach ($roots as $element_id) {
@@ -437,9 +446,9 @@ function tripal_update_cvtermpath_root_loop($rootid, $cvid, &$roots) {
   $roots[] = $term_id;
 
   // Descends through the branch starting at this "root" term.
-  $tree_path = array();
-  $matched_rows = array();
-  $possible_start_of_loop = array();
+  $tree_path = [];
+  $matched_rows = [];
+  $possible_start_of_loop = [];
   $depth = 0;
   tripal_update_cvtermpath_loop($rootid, $rootid, $cvid, $result->cvterm_id, $depth,
                                 0, $tree_path, FALSE, $matched_rows, $possible_start_of_loop, FALSE);
@@ -451,7 +460,7 @@ function tripal_update_cvtermpath_root_loop($rootid, $cvid, &$roots) {
       FROM cvterm_relationship
       WHERE object_id = :rootid
     ',
-    array(':rootid' => $rootid)
+    [':rootid' => $rootid]
   );
   while ($cterm_result = $cterm->fetchAssoc()) {
     tripal_update_cvtermpath_root_loop($cterm_result['subject_id'], $cvid, $roots);
@@ -510,7 +519,7 @@ function tripal_update_cvtermpath_loop(
   $no_loop_skip_test) {
 
   // We have not detected a loop, so it's safe to insert the term.
-  $new_match_rows = array();
+  $new_match_rows = [];
   if (!empty($possible_start_of_loop)) {
     // Go through each matched_row.
     if (count($matched_rows) === 1) {
@@ -523,7 +532,7 @@ function tripal_update_cvtermpath_loop(
           FROM cvtermpath
           WHERE cvtermpath_id = :cvtermpath_id
         ',
-        array(':cvtermpath_id' => $cvtermpath_id)
+        [':cvtermpath_id' => $cvtermpath_id]
       );
       $next_row = $next_row->fetchObject();
 
@@ -541,7 +550,7 @@ function tripal_update_cvtermpath_loop(
         // The next_row is equal to start of loop, so we've reached the end
         // and confirmed that this is a loop.
         $possible_loop == FALSE;
-        $matched_rows = array();
+        $matched_rows = [];
         tripal_update_cvtermpath_loop_increment($origin, $child_id, $cv_id,
         $type_id, $depth + 1, $increment_of_depth, $tree_path, $possible_loop,
         $new_match_rows, $possible_start_of_loop, $no_loop_skip_test);
@@ -560,7 +569,7 @@ function tripal_update_cvtermpath_loop(
             FROM cvtermpath
             WHERE cvtermpath_id = :cvtermpath_id
           ',
-          array(':cvtermpath_id' => $cvtermpath_id)
+          [':cvtermpath_id' => $cvtermpath_id]
         );
         $next_row = $next_row->fetchObject();
 
@@ -578,7 +587,7 @@ function tripal_update_cvtermpath_loop(
           // The next_row is equal to start of loop, so we've reached the end
           // and confirmed that this is a loop.
           $possible_loop == FALSE;
-          $matched_rows = array();
+          $matched_rows = [];
           tripal_update_cvtermpath_loop_increment($origin, $child_id, $cv_id,
           $type_id, $depth + 1, $increment_of_depth, $tree_path, $possible_loop,
           $new_match_rows, $possible_start_of_loop, $no_loop_skip_test);
@@ -589,7 +598,7 @@ function tripal_update_cvtermpath_loop(
     // If $match_rows is empty there is no loop.
     if (empty($new_match_rows)) {
       $possible_loop == FALSE;
-      $matched_rows = array();
+      $matched_rows = [];
       unset($new_match_rows);
       $no_loop_skip_test = TRUE;
       // There is not loop so pass it back the possible_start_of_loop info
@@ -669,20 +678,21 @@ function tripal_update_cvtermpath_loop_increment(
   if ($possible_loop === FALSE && empty($possible_start_of_loop)) {
     chado_set_active('chado');
     $count = db_query(
-      'SELECT *
+      ' SELECT *
         FROM cvtermpath
-        WHERE cv_id = :cvid
-        AND object_id = :origin
+        WHERE object_id = :origin
         AND subject_id = :child_id
         AND pathdistance = :depth
+        AND type_id = :type_id
       ',
-      array(
-        ':cvid' => $cv_id,
+      [
         ':origin' => $origin,
         ':child_id' => $child_id,
-        ':depth' => $depth
-      )
+        ':depth' => $depth,
+        ':type_id' => $type_id
+      ]
     );
+    $count->fetchAll();
     $count_total = $count->rowCount();
     if ($count_total > 0) {
       return $count;
@@ -691,7 +701,8 @@ function tripal_update_cvtermpath_loop_increment(
     $term_id = $origin . '|' . $child_id . '|' . $cv_id . '|' . $type_id;
 
     if ($no_loop_skip_test === FALSE) {
-      // Now check if the most recent entry already exists in the array.
+      // If the increment of depth is 0 then it's the first time and we need to skip
+      // the test so we can build the tree_path which will be tested against.
       if ($increment_of_depth != 0) {
         // Search the $tree_path for the new $child_id in the build_id column.
         foreach ($tree_path as $parent) {
@@ -702,19 +713,19 @@ function tripal_update_cvtermpath_loop_increment(
             $possible_loop = TRUE;
             // Find all the results in the table that might be the start of the loop.
             $matching_rows = db_query(
-              'SELECT *
-              FROM cvtermpath
-              WHERE cv_id = :cvid
-              AND object_id = :origin
-              AND subject_id = :child_id
-              AND type_id = :type_id
+              ' SELECT *
+                FROM cvtermpath
+                WHERE cv_id = :cvid
+                AND object_id = :origin
+                AND subject_id = :child_id
+                AND type_id = :type_id
               ',
-              array(
+              [
                 ':cvid' => $cv_id,
                 ':origin' => $origin,
                 ':child_id' => $child_id,
                 ':type_id' => $type_id
-              )
+              ]
             );
             $matched_rows = $matching_rows->fetchAll();
             $possible_start_of_loop = array(
@@ -736,7 +747,14 @@ function tripal_update_cvtermpath_loop_increment(
           'type_id' => $type_id,
           'pathdistance' => $depth,
         ]);
-      $rows = $query->execute();
+
+      try {
+        $rows = $query->execute();
+      } catch (Exception $e) {
+        $error = $e->getMessage();
+        tripal_report_error('tripal_chado', TRIPAL_ERROR, "Could not fill cvtermpath term: @error", array('@error' => $error));
+        return false;
+      }
 
       // Then add that new entry to the $tree_path.
       $tree_path[$increment_of_depth] = [
@@ -746,10 +764,10 @@ function tripal_update_cvtermpath_loop_increment(
     }
     // Reset to FALSE  and empty variable if passed in as TRUE.
     $no_loop_skip_test == FALSE;
-    $possible_start_of_loop = array();
+    $possible_start_of_loop = [];
 
     // Get all of the relationships of this child term, and recursively
-    // call the tripal_update_cvtermpath_loop() function to continue
+    // call the tripal_update_cvtermpath_loop_increment() function to continue
     // descending down the tree.
     $query = db_select('cvterm_relationship', 'cvtr')
       ->fields('cvtr')

+ 165 - 24
tripal_chado/includes/TripalImporter/OBOImporter.inc

@@ -239,7 +239,8 @@ class OBOImporter extends TripalImporter {
       '#type'          => 'textfield',
       '#title'         => t('New Vocabulary Name'),
       '#description'   => t('Please provide a name for this vocabulary.  After upload, this name will appear in the drop down
-                             list above for use again later.'),
+                             list above for use again later. Additionally, if a default namespace is not provided in the OBO
+                             header this name will be used as the default_namespace.'),
     );
 
     $form['obo_new']['obo_url']= array(
@@ -488,7 +489,7 @@ class OBOImporter extends TripalImporter {
       tripal_insert_obo($obo_name, $file);
     }
 
-    $success = $this->loadOBO_v1_2($file);
+    $success = $this->loadOBO_v1_2($file, $obo_name);
   }
 
   /**
@@ -531,7 +532,7 @@ class OBOImporter extends TripalImporter {
     }
 
     // second, parse the OBO
-    $this->loadOBO_v1_2($temp);
+    $this->loadOBO_v1_2($temp, $obo_name);
 
     // now remove the temp file
     unlink($temp);
@@ -549,8 +550,7 @@ class OBOImporter extends TripalImporter {
    *
    * @ingroup tripal_obo_loader
    */
-  private function loadOBO_v1_2($file) {
-
+  private function loadOBO_v1_2($file, $obo_name) {
     $header = array();
     $ret = array();
 
@@ -576,24 +576,52 @@ class OBOImporter extends TripalImporter {
     }
     // If the 'default-namespace' is missing.
     else {
-
-      // Look to see if an 'ontology' key is present.  It is part of the v1.4
-      // specification so it shouldn't be in the file, but just in case
-      if (array_key_exists('ontology', $header)) {
-        $defaultcv = tripal_insert_cv(strtoupper($header['ontology'][0]), '');
-        if (!$defaultcv) {
-          throw new Exception('Cannot add namespace ' . strtoupper($header['ontology'][0]));
+      // Grab the first term accession from the file and get the short name for the cv
+      $fh = fopen($file, 'r');
+      while ($line = fgets($fh)) {
+        // Grab the first item's id info to break apart.
+        if (preg_match('/^\s*\[/', $line)) {
+          $stanza = TRUE;
+          continue;
+        }
+        if ($stanza === TRUE && (substr($line, 0, 3) === "id:")) {
+          $parts = explode(':', $line);
+          $short_name = strtolower($parts[1]);
+          $short_name = preg_replace('/\s+/', '', $short_name);
+          break;
         }
-        $this->newcvs[strtoupper(strtoupper($header['ontology'][0]))] = $defaultcv->cv_id;
       }
-      else {
+      fclose($fh);
+      // Check if the EBI ontology search has this ontology:
+      try {
+        $results = $this->oboEbiLookup($short_name, 'ontology');
+        if (array_key_exists('default-namespace', $results['config']['annotations'])) {
+          $results = $results['config']['annotations']['default-namespace'];
+          if (is_array($results)) {
+            $results = $results[0];
+          }
+        }
+        elseif (array_key_exists('namespace', $results['config'])) {
+          $results = $results['config']['namespace'];
+        }
+        else {
+          $results = $short_name;
+        }
+        $defaultcv = tripal_insert_cv(strtoupper($results), '');
+        $this->newcvs[$defaultcv->name] = $defaultcv->cv_id;
+      }
+      catch (Exception $e) {
+        watchdog_exception('OBOImporter no such accession found in EBI Ontology Search', $e);
+      }
+    
+      if (empty($defaultcv)) {
         throw new Exception("Could not find a namespace for this OBO file: $file");
       }
       $this->logMessage("This OBO is missing the 'default-namespace' header. It " .
-          "is not possible to determine which vocabulary terms without a 'namespace' key " .
-          "should go.  Instead, those terms will be placed in the '!vocab' vocabulary.",
-          array('!vocab' => $defaultcv->name), TRIPAL_WARNING);
-    }!
+        "is not possible to determine which vocabulary terms without a 'namespace' key " .
+        "should go.  Instead, those terms will be placed in the '!vocab' vocabulary.",
+        array('!vocab' => $defaultcv->name), TRIPAL_WARNING);
+    }
     // Add any typedefs to the vocabulary first.
     $this->logMessage("Step 2: Loading type defs...");
     $this->loadTypeDefs($defaultcv, $default_db);
@@ -713,8 +741,7 @@ class OBOImporter extends TripalImporter {
     if (!array_key_exists('namespace', $term) and !($defaultcv or $defaultcv == '')) {
       throw new Exception("Cannot add the term: no namespace defined. " . $term['id'][0]);
     }
-
-    // construct the term array for sending to the tripal_chado_add_cvterm function
+   // construct the term array for sending to the tripal_chado_add_cvterm function
     // for adding a new cvterm
     $t = array();
     $t['id'] = $term['id'][0];
@@ -732,6 +759,32 @@ class OBOImporter extends TripalImporter {
       $t['is_obsolete'] = $term['is_obsolete'][0];
     }
 
+    // Check that the default_cv is in the cv table.
+    $sql =  "
+      SELECT CV.name 
+      FROM {cv} CV 
+      WHERE CV.name = '$defaultcv'
+    ";
+    $results = chado_query($sql)->fetchObject();
+    if (!$results){
+      //The controlled vocabulary is not in the cv term table and needs to be added.
+      $ontology_info = $this->oboEbiLookup($defaultcv, 'ontology');
+      if (!empty($ontology_info)){
+        if (array_key_exists('default-namespace', $ontology_info['config']['annotations'])) {
+          $results = $ontology_info['config']['annotations']['default-namespace'];
+        }
+        elseif (array_key_exists('namespace', $ontology_info['config'])) {
+          $results = $ontology_info['config']['namespace'];
+        }
+        $cv_returned = tripal_insert_cv($results[0], '');
+        // If name && definition are both empty then look up the term from the ontology you just loaded.
+        if($cv_returned) {
+          $defaultcv = $cv_returned;
+        }
+      }
+    }
+ 
+
     $t['cv_name'] = $defaultcv;
     $t['is_relationship'] = $is_relationship;
     $t['db_name'] = $default_db;
@@ -902,7 +955,42 @@ class OBOImporter extends TripalImporter {
    */
   private function addRelationship($cvterm, $defaultcv, $rel,
       $objname, $object_is_relationship = 0, $default_db = 'OBO_REL') {
-
+    // If an accession was passed we need to see if we can find the actual label.
+    if (strpos($rel, ':')) {
+      $pair = explode(":", $rel);    
+      $ontology_id = $pair[0];
+      $accession_num = $pair[1];
+      if (is_numeric($accession_num)) {
+        $results = $this->oboEbiLookup($rel, 'query');
+        if (!empty($results)) {
+          if (array_key_exists('docs', $results)){
+            if(!empty($results['docs'])) {
+              $rel = $results['docs']['label'];
+            }
+            else {
+              // The first search doesn't work, so let's try a broader one.
+              $results = $this->oboEbiLookup($rel, 'query-non-local');
+              if (!empty($results)) {
+                if (array_key_exists('docs', $results)){
+                  if(!empty($results['docs'])) {
+                    $accession = $rel;
+                    $accession_underscore = str_replace(":", "_", $accession);
+                    foreach ($results['docs'] as $item) {
+                      if ($item['label'] != $accession && $item['label'] != $accession_underscore) {
+                        //Found the first place a label is other than the accession is used, so take
+                        // that info and then end the loop.
+                        $rel = $item['label'];
+                        break;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }    
     // Make sure the relationship cvterm exists.
     $term = array(
       'name' => $rel,
@@ -932,7 +1020,7 @@ class OBOImporter extends TripalImporter {
         throw new Exception("Cannot find the relationship term in the current ontology or in the relationship ontology: $rel\n");
       }
     }
-
+  
     // Get the object term.
     $oterm = $this->getTerm($objname);
     if (!$oterm) {
@@ -1120,7 +1208,6 @@ class OBOImporter extends TripalImporter {
     // iterate through the lines in the OBO file and parse the stanzas
     $fh = fopen($obo_file, 'r');
     while ($line = fgets($fh)) {
-
       $line_num++;
       $size = drupal_strlen($line);
       $num_read += $size;
@@ -1178,7 +1265,6 @@ class OBOImporter extends TripalImporter {
       if ($tag == 'id' and preg_match('/^(.+?):.*$/', $value, $matches)) {
         $default_db = $matches[1];
       }
-
       $tag = preg_replace("/\|-\|-\|/", "\:", $tag); // return the escaped colon
       $value = preg_replace("/\|-\|-\|/", "\:", $value);
       if ($in_header) {
@@ -1374,6 +1460,60 @@ class OBOImporter extends TripalImporter {
     }
     return $result[0];
   }
+
+
+  /**
+   * API call to Ontology Lookup Service provided by
+   * https://www.ebi.ac.uk/ols/docs/api#resources-terms
+   *
+   * @param accession
+   *   Accession term for query
+   * @param type_of_search
+   *   Either ontology, term, query, or query-non-local
+   *
+   * @ingroup tripal_obo_loader
+   */
+  private function oboEbiLookup($accession, $type_of_search) {
+    //Grab just the ontology from the $accession.
+    $parts = explode(':', $accession);
+    $ontology = strtolower($parts[0]);
+    $ontology = preg_replace('/\s+/', '', $ontology);
+    if ($type_of_search == 'ontology') {
+      $options = array();
+      $full_url = 'http://www.ebi.ac.uk/ols/api/ontologies/' . $ontology;
+      $response = drupal_http_request($full_url, $options);
+      if(!empty($response)){
+        $response = drupal_json_decode($response->data);
+      }
+    }
+    elseif ($type_of_search == 'term') {
+      //The IRI of the terms, this value must be double URL encoded
+      $iri = urlencode(urlencode("http://purl.obolibrary.org/obo/" . str_replace(':' , '_', $accession)));
+      $options = array();
+      $full_url = 'http://www.ebi.ac.uk/ols/api/ontologies/' . $ontology . '/' . 'terms/' . $iri;
+      $response = drupal_http_request($full_url, $options);
+      if(!empty($response)){
+        $response = drupal_json_decode($response->data);
+      }
+    }
+    elseif($type_of_search == 'query') {    
+      $options = array();
+      $full_url = 'http://www.ebi.ac.uk/ols/api/search?q=' . $accession . '&queryFields=obo_id&local=true';
+      $response = drupal_http_request($full_url, $options);
+      if(!empty($response)){
+        $response = drupal_json_decode($response->data);
+      }
+    }
+    elseif($type_of_search == 'query-non-local') {    
+      $options = array();
+      $full_url = 'http://www.ebi.ac.uk/ols/api/search?q=' . $accession . '&queryFields=obo_id';
+      $response = drupal_http_request($full_url, $options);
+      if(!empty($response)){
+        $response = drupal_json_decode($response->data);
+      }
+    }
+    return $response;
+  }
 }
 
 /**
@@ -1382,3 +1522,4 @@ class OBOImporter extends TripalImporter {
 function tripal_cv_obo_form_ajax_callback($form, $form_state) {
   return $form['class_elements']['obo_existing'];
 }
+

+ 0 - 0
tripal_chado/includes/tripal_chado.cv.inc