Sfoglia il codice sorgente

Fixed bug where featurelocs weren't showing up if one of the two FK relationships returned NULL

spficklin 12 anni fa
parent
commit
a52dc176d2
2 ha cambiato i file con 177 aggiunte e 138 eliminazioni
  1. 83 40
      tripal_core/api/tripal_core.api.inc
  2. 94 98
      tripal_feature/tripal_feature.module

+ 83 - 40
tripal_core/api/tripal_core.api.inc

@@ -391,28 +391,28 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
  * Example usage:
  * @code
  $umatch = array(
- 'organism_id' => array(
- 'genus' => 'Citrus',
- 'species' => 'sinensis',
- ),
- 'uniquename' => 'orange1.1g000034m.g7',
- 'type_id' => array (
- 'cv_id' => array (
- 'name' => 'sequence',
- ),
- 'name' => 'gene',
- 'is_obsolete' => 0
- ),
+   'organism_id' => array(
+     'genus' => 'Citrus',
+     'species' => 'sinensis',
+   ),
+   'uniquename' => 'orange1.1g000034m.g7',
+   'type_id' => array (
+     'cv_id' => array (
+       'name' => 'sequence',
+     ),
+     'name' => 'gene',
+     'is_obsolete' => 0
+   ),
  );
  $uvalues = array(
- 'name' => 'orange1.1g000034m.g',
- 'type_id' => array (
- 'cv_id' => array (
- 'name' => 'sequence',
- ),
- 'name' => 'mRNA',
- 'is_obsolete' => 0
- ),
+   'name' => 'orange1.1g000034m.g',
+   'type_id' => array (
+     'cv_id' => array (
+       'name' => 'sequence',
+     ),
+     'name' => 'mRNA',
+     'is_obsolete' => 0
+   ),
  );
  *   $result = tripal_core_chado_update('feature',$umatch,$uvalues);
  * @endcode
@@ -1413,18 +1413,30 @@ function tripal_core_chado_get_foreign_key($table_desc, $field, $values, $option
  *   option of 'order_by' may be used to sort results in the base table
  *   if more than one are returned.  The options must be compatible with
  *   the options accepted by the tripal_core_chado_select() function.
- *   Additionally,  The option 'return_array' can be provided to force
- *   the function to always return an array. Default behavior is to return
- *   a single record if only one record exists or to return an array if
- *   multiple records exist.
+ *   Additionally,  These options are available for this function:
+ *   -return_array: 
+ *     can be provided to force the function to always return an array. Default 
+ *     behavior is to return a single record if only one record exists or to return 
+ *     an array if multiple records exist.
+ *  - include_fk: 
+ *     an array of FK relationships to fallow. By default, the 
+ *     tripal_core_chado_select function will follow all FK relationships but this
+ *     may generate more queries then is desired.  Provide an array specifying the
+ *     fields to include.  For example, if including the cvterm, cv and dbxref records
+ *     for a property the following array would work:
+ *        array('type_id' => array('cv_id' => 1, 'dbxref_id' => 1)).
+ *     Typicall, to expadn a property, this function would also include the db record 
+ *     through the db_id foreign key with the dbxref and db tables, but becuase 
+ *     it is not included in the array it will not be included in the results.
  * @return
  *   Either an object (if only one record was selected from the base table)
  *   or an array of objects (if more than one record was selected from the base table).
+ *   If the option 'return_array' is provided the function always returns an array.
  *
  * Example Usage:
  * @code
  $values = array(
- 'name' => 'Medtr4g030710'
+   'name' => 'Medtr4g030710'
  );
  $features = tripal_core_generate_chado_var('feature', $values);
  * @endcode
@@ -1438,7 +1450,7 @@ function tripal_core_chado_get_foreign_key($table_desc, $field, $values, $option
  *      this hook to return an array of fields to be excluded. For example:
  * @code
  mymodule_exclude_field_from_feature_by_default() {
- return array('residues' => TRUE);
+   return array('residues' => TRUE);
  }
  * @endcode
  *      will ensure that feature.residues is ecluded from a feature object by default.
@@ -1449,7 +1461,7 @@ function tripal_core_chado_get_foreign_key($table_desc, $field, $values, $option
  *      any table. Tokens available in criteria are >field_value<  and >field_name< . For example:
  * @code
  mymodule_exclude_type_by_default() {
- return array('text' => 'length(>field_value< ) > 50');
+   return array('text' => 'length(>field_value< ) > 50');
  }
  * @endcode
  *      will exclude all text fields with a length > 50. Thus if $feature.residues is longer than 50 *      it will be excluded, otherwise it will be added.
@@ -1463,6 +1475,10 @@ function tripal_core_generate_chado_var($table, $values, $base_options = array()
   if(array_key_exists('return_array', $base_options)){
   	$return_array = 1;
   }
+  $include_fk = 0;
+  if(array_key_exists('include_fk', $base_options)){
+    $include_fk = $base_options['include_fk'];
+  }
 
   // get description for the current table----------------------------------------------------------
   $table_desc = tripal_core_get_chado_table_schema($table);
@@ -1606,9 +1622,25 @@ function tripal_core_generate_chado_var($table, $values, $base_options = array()
             if (empty($object->{$foreign_key})) {
               continue;
             }
+            
+            if ($include_fk) {
+            	// don't recurse if the callee has supplied an $fk_include list and this 
+              // FK table is not in the list.
+            	if(is_array($include_fk) and !array_key_exists($foreign_key, $include_fk)){
+                continue;
+            	}
+            	// if we have the option but it is not an array then we don't recurse any furutehr
+            	if (!is_array($include_fk)) {
+            		continue;
+            	}	
+            } 
             // get the record from the foreign table
             $foreign_values = array($primary_key => $object->{$foreign_key});
-            $foreign_object = tripal_core_generate_chado_var($foreign_table, $foreign_values);
+            $options = array();
+            if(is_array($include_fk)){            	
+              $options['include_fk'] = $include_fk[$foreign_key];
+            }
+            $foreign_object = tripal_core_generate_chado_var($foreign_table, $foreign_values, $options);
             // add the foreign record to the current object in a nested manner
             $object->{$foreign_key} = $foreign_object;
             // Flatten expandable_x arrays so only in the bottom object
@@ -1692,17 +1724,17 @@ function tripal_core_generate_chado_var($table, $values, $base_options = array()
  *
  * Example Usage:
  * @code
- // Get a chado object to be expanded
- $values = array(
- 'name' => 'Medtr4g030710'
- );
- $features = tripal_core_generate_chado_var('feature', $values);
- // Expand the organism node
- $feature = tripal_core_expand_chado_vars($feature, 'node', 'organism');
- // Expand the feature.residues field
- $feature = tripal_core_expand_chado_vars($feature, 'field', 'feature.residues');
- // Expand the feature properties (featureprop table)
- $feature = tripal_core_expand_chado_vars($feature, 'table', 'featureprop');
+   // Get a chado object to be expanded
+   $values = array(
+     'name' => 'Medtr4g030710'
+   );
+   $features = tripal_core_generate_chado_var('feature', $values);
+   // Expand the organism node
+   $feature = tripal_core_expand_chado_vars($feature, 'node', 'organism');
+   // Expand the feature.residues field
+   $feature = tripal_core_expand_chado_vars($feature, 'field', 'feature.residues');
+   // Expand the feature properties (featureprop table)
+   $feature = tripal_core_expand_chado_vars($feature, 'table', 'featureprop');
  * @endcode
  *
  * @ingroup tripal_chado_api
@@ -1753,6 +1785,11 @@ function tripal_core_expand_chado_vars($object, $type, $to_expand, $table_option
       break;
     case "table": //--------------------------------------------------------------------------------
       $foreign_table = $to_expand;
+      
+      // don't expand the table it already is expanded
+      if(array_key_exists($foreign_table, $object)){
+      	return;
+      }
       $foreign_table_desc = tripal_core_get_chado_table_schema($foreign_table);
       // If it's connected to the base table
       if ($foreign_table_desc['foreign keys'][$base_table]) {
@@ -1788,8 +1825,14 @@ function tripal_core_expand_chado_vars($object, $type, $to_expand, $table_option
               $object->expanded = $to_expand;
             }
           }
+          // if the object returned is NULL then handle that
           else {
-            $object->{$foreign_table} = NULL;  
+          	if (count($foreign_table_desc['foreign keys'][$base_table]['columns']) > 1) {
+              $object->{$foreign_table}->{$left} = NULL;                 
+          	}
+          	else {
+          		$object->{$foreign_table} = NULL;
+          	}
           }
         }
       }

+ 94 - 98
tripal_feature/tripal_feature.module

@@ -1957,28 +1957,19 @@ function tripal_feature_preprocess_tripal_feature_relationships(&$variables) {
   $feature = $variables['node']->feature;
    
   // expand the feature object to include the feature relationships.
-  $feature = tripal_core_expand_chado_vars($feature,
-     'table','feature_relationship', array('order_by'=>array('rank' => 'ASC')));
+  $options = array(
+    'return_array' => 1,
+    'order_by'     => array('rank' => 'ASC'),
+  );
+  $feature = tripal_core_expand_chado_vars($feature, 'table',
+    'feature_relationship', $options);
 
   // get the subject relationships
   $srelationships = $feature->feature_relationship->subject_id;
-  if (!$srelationships) {
-     $srelationships = array();
-  } 
-  elseif (!is_array($srelationships)) { 
-     $srelationships = array($srelationships); 
-  }
-  
-  // get the object relationships
   $orelationships = $feature->feature_relationship->object_id;
-  if (!$orelationships) {
-     $orelationships = array();
-  } 
-  elseif (!is_array($orelationships)) { 
-     $orelationships = array($orelationships); 
-  }
   
-  // get alignment as child
+  // get alignment as child. The $feature->featureloc element
+  // is already populated from the alignment preprocess function
   $cfeaturelocs = $feature->featureloc->feature_id;
   if (!$cfeaturelocs) {
      $cfeaturelocs = array();
@@ -1986,23 +1977,21 @@ function tripal_feature_preprocess_tripal_feature_relationships(&$variables) {
   elseif (!is_array($cfeaturelocs)) { 
      $cfeaturelocs = array($cfeaturelocs); 
   }
-
   
   // prepare the SQL statement to get the featureloc for the 
   // feature in the relationships. 
-  if(!tripal_core_is_sql_prepared('sel_featureloc_preprocess_relationships')){
-    $psql = "PREPARE sel_featureloc_preprocess_relationships (int, int) AS " .
-            "SELECT FL.featureloc_id, F.name as srcfeature_name, FL.srcfeature_id, ".
-            "  FL.feature_id, FL.fmin, FL.fmax, FL.strand, FL.phase ".
-            "FROM featureloc FL " .
-            "  INNER JOIN feature F ON F.feature_id = FL.srcfeature_id ".
-            "WHERE FL.feature_id = $1 and FL.srcfeature_id = $2";
-    $prepared = chado_query($psql);
-    if(!$prepared){
-      watchdog('tripal_feature', "tripal_feature_preprocess_tripal_feature_relationships: not able to prepare '%name' statement for: %sql", array('%name' => 'sel_featureloc_preprocess_relationships', '%sql' => $psql), 'WATCHDOG ERROR');
-      return FALSE;
-    }
-  }  
+  $connection = tripal_db_persistent_chado();
+  $psql = " 
+    PREPARE sel_featureloc_preprocess_relationships (int, int) AS 
+    SELECT 
+      FL.featureloc_id, F.name as srcfeature_name, FL.srcfeature_id,
+      FL.feature_id, FL.fmin, FL.fmax, FL.strand, FL.phase
+    FROM featureloc FL 
+      INNER JOIN feature F ON F.feature_id = FL.srcfeature_id
+    WHERE FL.feature_id = $1 and FL.srcfeature_id = $2
+  ";
+  tripal_core_chado_prepare('sel_featureloc_preprocess_relationships', $psql, array('int', 'int'));
+
   
   // combine both object and subject relationshisp into a single array
   $relationships = array();
@@ -2010,76 +1999,80 @@ function tripal_feature_preprocess_tripal_feature_relationships(&$variables) {
   $relationships['subject'] = array();
   
   // iterate through the object relationships
-  foreach ($orelationships as $relationship) {
-     $rel = new stdClass(); 
-     // get locations where the child feature and this feature overlap with the
-     // same landmark feature.
-     $rel->child_featurelocs = array();     
-     foreach ($cfeaturelocs as $featureloc) {
-        $res = chado_query("EXECUTE sel_featureloc_preprocess_relationships (%d, %d)", 
-          $relationship->subject_id->feature_id, 
-          $featureloc->srcfeature_id->feature_id);        
-        while ($loc = db_fetch_object($res)){
-           // add in the node id of the src feature if it exists and save this location
-           $loc->nid = $featureloc->srcfeature_id->nid;
-           $rel->child_featurelocs[] = $loc;
-        }
-     }
-     $rel->record = $relationship;    
-     
-     // get the relationship and child types
-     $rel_type = t(preg_replace('/_/'," ",$relationship->type_id->name));
-     $child_type = $relationship->subject_id->type_id->name;
-     
-     // get the node id of the subject
-     $sql = "SELECT nid FROM chado_feature WHERE feature_id = %d";
-     $n = db_fetch_object(db_query($sql,$relationship->subject_id->feature_id));
-     if($n){
-        $rel->record->nid = $n->nid;
-     }
-
-     if (!array_key_exists($rel_type, $relationships['object'])) {
-       $relationships['object'][$rel_type] = array();   
-     }
-     if (!array_key_exists($child_type, $relationships['object'][$rel_type])) {
-       $relationships['object'][$rel_type][$child_type] = array();   
-     }
-     $relationships['object'][$rel_type][$child_type][] = $rel;     
+  if ($orelationships) {
+	  foreach ($orelationships as $relationship) {
+	     $rel = new stdClass(); 
+	     // get locations where the child feature and this feature overlap with the
+	     // same landmark feature.
+	     $rel->child_featurelocs = array();     
+	     foreach ($cfeaturelocs as $featureloc) {
+	        $res = chado_query("EXECUTE sel_featureloc_preprocess_relationships (%d, %d)", 
+	          $relationship->subject_id->feature_id, 
+	          $featureloc->srcfeature_id->feature_id);        
+	        while ($loc = db_fetch_object($res)){
+	           // add in the node id of the src feature if it exists and save this location
+	           $loc->nid = $featureloc->srcfeature_id->nid;
+	           $rel->child_featurelocs[] = $loc;
+	        }
+	     }
+	     $rel->record = $relationship;    
+	     
+	     // get the relationship and child types
+	     $rel_type = t(preg_replace('/_/'," ",$relationship->type_id->name));
+	     $child_type = $relationship->subject_id->type_id->name;
+	     
+	     // get the node id of the subject
+	     $sql = "SELECT nid FROM chado_feature WHERE feature_id = %d";
+	     $n = db_fetch_object(db_query($sql,$relationship->subject_id->feature_id));
+	     if($n){
+	        $rel->record->nid = $n->nid;
+	     }
+	
+	     if (!array_key_exists($rel_type, $relationships['object'])) {
+	       $relationships['object'][$rel_type] = array();   
+	     }
+	     if (!array_key_exists($child_type, $relationships['object'][$rel_type])) {
+	       $relationships['object'][$rel_type][$child_type] = array();   
+	     }
+	     $relationships['object'][$rel_type][$child_type][] = $rel;     
+	  }
   }
   
   // now add in the subject relationships
-  foreach ($srelationships as $relationship) {
-     $rel = new stdClass(); 
-     // get locations where this feature overlaps with the parent
-     $rel->parent_featurelocs = array();     
-     foreach ($cfeaturelocs as $featureloc) {
-        $res = chado_query("EXECUTE sel_featureloc_preprocess_relationships (%d, %d)", 
-          $relationship->object_id->feature_id, 
-          $featureloc->srcfeature_id->feature_id);
-        while ($loc = db_fetch_object($res)){
-           // add in the node id of the src feature if it exists and save this location
-           $loc->nid = $featureloc->srcfeature_id->nid;
-           $rel->parent_featurelocs[] = $loc;
-        }
-     }
-     $rel->record = $relationship;
-     $rel_type = t(preg_replace('/_/'," ",$relationship->type_id->name));
-     $parent_type = $relationship->object_id->type_id->name;
-     
-     // get the node id of the subject
-     $sql = "SELECT nid FROM chado_feature WHERE feature_id = %d";
-     $n = db_fetch_object(db_query($sql,$relationship->object_id->feature_id));
-     if($n){
-        $rel->record->nid = $n->nid;
-     }
-     
-     if (!array_key_exists($rel_type, $relationships['subject'])) {
-       $relationships['subject'][$rel_type] = array();   
-     }
-     if (!array_key_exists($child_type, $relationships['subject'][$rel_type])) {
-       $relationships['subject'][$rel_type][$parent_type] = array();   
-     }
-     $relationships['subject'][$rel_type][$parent_type][] = $rel;
+  if ($srelationships) {
+	  foreach ($srelationships as $relationship) {
+	     $rel = new stdClass(); 
+	     // get locations where this feature overlaps with the parent
+	     $rel->parent_featurelocs = array();     
+	     foreach ($cfeaturelocs as $featureloc) {
+	        $res = chado_query("EXECUTE sel_featureloc_preprocess_relationships (%d, %d)", 
+	          $relationship->object_id->feature_id, 
+	          $featureloc->srcfeature_id->feature_id);
+	        while ($loc = db_fetch_object($res)){
+	           // add in the node id of the src feature if it exists and save this location
+	           $loc->nid = $featureloc->srcfeature_id->nid;
+	           $rel->parent_featurelocs[] = $loc;
+	        }
+	     }
+	     $rel->record = $relationship;
+	     $rel_type = t(preg_replace('/_/'," ",$relationship->type_id->name));
+	     $parent_type = $relationship->object_id->type_id->name;
+	     
+	     // get the node id of the subject
+	     $sql = "SELECT nid FROM chado_feature WHERE feature_id = %d";
+	     $n = db_fetch_object(db_query($sql,$relationship->object_id->feature_id));
+	     if($n){
+	        $rel->record->nid = $n->nid;
+	     }
+	     
+	     if (!array_key_exists($rel_type, $relationships['subject'])) {
+	       $relationships['subject'][$rel_type] = array();   
+	     }
+	     if (!array_key_exists($child_type, $relationships['subject'][$rel_type])) {
+	       $relationships['subject'][$rel_type][$parent_type] = array();   
+	     }
+	     $relationships['subject'][$rel_type][$parent_type][] = $rel;
+	  }
   }
   $feature->all_relationships = $relationships;
 
@@ -2092,6 +2085,9 @@ function tripal_feature_preprocess_tripal_feature_relationships(&$variables) {
 function tripal_feature_preprocess_tripal_feature_alignments(&$variables) {
   // we want to provide a new variable that contains the matched features.
   $feature = $variables['node']->feature;
+
+  $feature = tripal_core_expand_chado_vars($feature, 'table', 'featureloc');
+  $variables['node']->feature = $feature;
   
   // get alignments as child
   $cfeaturelocs = $feature->featureloc->feature_id;