Browse Source

Aggregator: Added basic many2one join handler

Lacey Sanderson 13 năm trước cách đây
mục cha
commit
3c7510cc12

+ 32 - 1
base/tripal_analysis/views/analysis.views.inc

@@ -62,7 +62,38 @@ function retrieve_analysis_views_data() {
     'handler' => 'views_handler_join_chado_through_linking'
   );
 
-	
+  // Analysis properties?
+ 	$data['analysisprop']['table'] = array(
+'group' => 'Chado analysis Properties',
+ 		'field' => 'analysisprop_id',
+ 		'title' => t('Chado analysis Properties'),
+ 		'help' => '  ',
+ 	);
+ 	
+ 	$data['analysisprop']['table']['join']['analysis'] = array(
+    'left_field' => 'analysis_id',
+    'field' => 'analysis_id',
+    'handler' => 'views_handler_join_chado_aggregator'
+ 	);
+ 	
+ 	$data['analysisprop']['value'] = array(
+    'title' => t('Value'),
+    'help' => t(' '),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+ 	);
+ 	
 	// Table Field Definitions----------------------
 	// Field: analysis_id (primary key)
 	$data['analysis']['analysis_id'] = array(

+ 1 - 1
base/tripal_core/tripal_core.views.inc

@@ -1,7 +1,7 @@
 <?php
 
 include('views/handlers/views_handler_join_chado_through_linking.inc');
-//include('views/handlers/views_handler_join_chado_one2many.inc');
+include('views/handlers/views_handler_join_chado_aggregator.inc');
 
 /**
  * @defgroup views Views Integration

+ 109 - 0
base/tripal_core/views/handlers/views_handler_join_chado_aggregator.inc

@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * Handler to allow joins between records via a linking table
+ *
+ * Example Usage:
+ *   To join the analysisprop table to the analysis table,
+ *   Use the following code in the analysisprop hook_views_data:
+ *   @code
+        $data['analysisprop']['table']['join']['analysis'] = array(
+          'left_field' => 'analysis_id',
+          'field' => 'analysis_id',
+          'handler' => 'views_handler_join_chado_aggregator'
+        );
+ *   @endcode
+ */
+class views_handler_join_chado_aggregator extends views_join {
+
+  // PHP 4 doesn't call constructors of the base class automatically from a
+  // constructor of a derived class. It is your responsibility to propagate
+  // the call to constructors upstream where appropriate.
+  function construct($table = NULL, $left_table = NULL, $left_field = NULL, $field = NULL, $extra = array(), $type = 'LEFT', $added = NULL) {
+    parent::construct($table, $left_table, $left_field, $field, $extra, $type);
+  }
+
+  /**
+   * Creates SQL including aggregation query used in join
+   */
+  function join($table, &$query) {
+    $output = '';
+    $joins = array();
+
+    // Create the table SQL (used in join) -------
+    // query creating one-to-one table using array_agg
+    $table_desc = module_invoke_all('chado_'.$this->definition['table'].'_schema');
+
+    // Fields to be selected
+    $fields = array();
+    foreach ($table_desc['fields'] as $fname => $f) {
+      if ($fname != $this->definition['field']) {
+        $fields[] = 'array_agg('.$fname.') as '.$fname;
+        $composite_field_parts[] = "'".$fname."::' ||".$fname;
+      } else {
+        $fields[] = $fname;
+      }
+    }
+    
+    // composite field 
+    // (combines all other fields before aggregating)
+    $composite_field = "array_agg('{'||".implode(" || ',' || ",$composite_field_parts)."||'}') as all";
+    $fields[] = $composite_field;
+    
+    // SQL to use in the join
+    $sql = 'SELECT '.implode(', ',$fields).' FROM '.$this->definition['table'].' GROUP BY '.$this->definition['field'];
+   
+    // Create the join (full SQL) ----------------
+    $joins[] = $this->create_single_join(
+      $query,
+      array(
+        'table' => $this->definition['table'],
+        'field' => $this->definition['field'],
+        'table_sql' => $sql,
+        'is_drupal' => FALSE,
+      ),
+      array(
+        'table' => $this->definition['left_table'],
+        'field' => $this->definition['left_field'],
+      ),
+      'LEFT'
+    );
+    
+    $output .= implode("\n",$joins);
+    return $output;
+  }
+  
+  /**
+   * Creates SQL for a single join based on parameters
+   * Join will be: <type> JOIN (<query creating one-to-one table using array_agg>) <table alias> 
+   *                  ON <qualified left field>=<qualified right field>
+   */
+  function create_single_join (&$query, $right_spec, $left_spec, $join_type) {
+    
+    if ($right_spec['table']) {
+      $right = $query->get_table_info($right_spec['table']);
+      if (!$right['alias']) { $right['alias'] = $right_spec['table']; }
+      $right_field = "$right[alias].$right_spec[field]";
+
+      if ($right_spec['is_drupal']) {
+        $right_table = '{'.$right_spec['table'].'}';
+      } else {
+        $right_table = $right_spec['table'];
+      }
+    }   
+
+    if ($left_spec['table']) {
+      $left = $query->get_table_info($left_spec['table']);
+      if (!$left['alias']) { $left['alias'] = $left_spec['table']; }
+      $left_field = "$left[alias].$left_spec[field]";
+    } else {
+      // This can be used if left_field is a formula or something. It should be used only *very* rarely.
+      $left_field = $this->left_spec['field'];
+    }
+    
+    $output = " $join_type JOIN ($right_spec[table_sql]) $right[alias] ON $left_field = $right_field";
+     
+    return $output;
+  }
+ 
+}