|
@@ -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;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|