Browse Source

Merged in newest 6.x-1482618-API_for_default_views_integration which includes all the specialty handlers

Lacey Sanderson 12 years ago
parent
commit
7c4d981d4e

+ 17 - 3
tripal_views/tripal_views.api.inc

@@ -434,6 +434,20 @@ function tripal_views_get_integration_array_for_chado_table($table_name, $base_t
           'sort' => array('name' => 'chado_views_handler_sort'),
         );
       }
+      elseif (preg_match('/^boolean/', $field_schema['type'])) {
+        $defn_array['fields'][$field_name]['handlers'] = array(
+          'field' => array('name' => 'chado_views_handler_field_boolean'),
+          'filter' => array('name' => 'chado_views_handler_filter_boolean_operator'),
+          'sort' => array('name' => 'chado_views_handler_sort'),
+        );
+      }
+      elseif (preg_match('/^datetime/', $field_schema['type'])) {
+        $defn_array['fields'][$field_name]['handlers'] = array(
+          'field' => array('name' => 'chado_views_handler_field_date'),
+          'filter' => array('name' => 'chado_views_handler_filter_date'),
+          'sort' => array('name' => 'views_handler_sort_date'),
+        );
+      }
       else {
         $defn_array['fields'][$field_name]['handlers'] = array(
           'field' => array('name' => 'chado_views_handler_field'),
@@ -443,8 +457,8 @@ function tripal_views_get_integration_array_for_chado_table($table_name, $base_t
       }
 
       // Specify specialty handlers
-      if ($field_name == 'type_id') {
-        $defn_array['fields'][$field_name]['handlers']['filter']['name'] = 'views_handler_filter_chado_select_cvterm_name';
+      if ($field_name == 'type_id' OR $field_name == 'cvterm_id') {
+        $defn_array['fields'][$field_name]['handlers']['filter']['name'] = 'chado_views_handler_filter_select_cvterm';
       }
     }
   }
@@ -459,7 +473,7 @@ function tripal_views_get_integration_array_for_chado_table($table_name, $base_t
       $defn_array['fields'][$left_field]['joins'][ $foreign_key_schema['table'] ] = array(
         'table' => $foreign_key_schema['table'],
         'field' => $right_field,
-        'handler' => 'views_handler_join_chado_aggregtor'
+        'handler' => 'views_handler_join_chado_aggregator'
       );
     }
   }

+ 15 - 29
tripal_views/tripal_views.views.inc

@@ -66,11 +66,11 @@ function tripal_views_views_handlers() {
       'chado_views_handler_field_aggregate' => array(
         'parent' => 'chado_views_handler_field',
       ),
-      'views_handler_filter_chado_select_string' => array(
-        'parent' => 'views_handler_filter_string',
+      'chado_views_handler_filter_select_cvterm' => array(
+        'parent' => 'views_handler_filter_chado_select_cvterm_name',
       ),
-      'views_handler_filter_chado_select_cvterm_name' => array(
-        'parent' => 'views_handler_filter_string',
+      'chado_views_handler_filter_select_string' => array(
+        'parent' => 'chado_views_handler_filter_string',
       ),
 
       // Join Handlers
@@ -86,19 +86,13 @@ function tripal_views_views_handlers() {
         'parent' => 'views_handler_filter'
       ),
 
-      // Old Handlers
+      // Old Handlers (deprecated)
       'views_handler_field_node_optional' => array(
         'parent' => 'views_handler_field_node',
       ),
-      'views_handler_field_chado_tf_boolean' => array(
-        'parent' => 'views_handler_field_boolean',
-      ),
       'views_handler_field_chado_count' => array(
         'parent' => 'views_handler_field',
       ),
-      'views_handler_filter_chado_boolean' => array(
-        'parent' => 'views_handler_filter_boolean_operator',
-      ),
       'views_handler_field_dbxref_accession_link' => array(
         'parent' => 'views_handler_field',
       ),
@@ -106,6 +100,13 @@ function tripal_views_views_handlers() {
         'parent' => 'views_handler_field',
       ),
 
+      // Old handlers with new counterparts (deprecated)
+      'views_handler_filter_chado_select_string' => array(
+        'parent' => 'views_handler_filter_string',
+      ),
+      'views_handler_filter_chado_select_cvterm_name' => array(
+        'parent' => 'views_handler_filter_string',
+      ),
 
       // Wrappers for Default Views Handlers-----
       // Field Handlers
@@ -137,9 +138,6 @@ function tripal_views_views_handlers() {
       'chado_views_handler_filter_string' => array(
         'parent' => 'views_handler_filter_string',
       ),
-      'chado_views_handler_filter_boolean_operator_string' => array(
-        'parent' => 'views_handler_filter_boolean_operator_string',
-      ),
       'chado_views_handler_filter_boolean_operator' => array(
         'parent' => 'views_handler_filter_boolean_operator',
       ),
@@ -163,18 +161,6 @@ function tripal_views_views_handlers() {
       'chado_views_handler_sort' => array(
         'parent' => 'views_handler_sort'
       ),
-      'chado_views_handler_sort_date' => array(
-        'parent' => 'views_handler_sort_date'
-      ),
-      'chado_views_handler_sort_formula' => array(
-        'parent' => 'views_handler_sort_formula'
-      ),
-      'chado_views_handler_sort_menu_hierarchy' => array(
-        'parent' => 'views_handler_sort_menu_hierarchy'
-      ),
-      'chado_views_handler_sort_random' => array(
-        'parent' => 'views_handler_sort_random'
-      ),
     ),
   );
 }
@@ -721,12 +707,12 @@ function tripal_views_data_export_download_form(&$form_state, $view, $display_id
   $current_display = $view->current_display;
   foreach ($displays as $name => $display) {
     if (preg_match("/^views_data_export/", $name)) {
-    
-      // only add this display to the form if it is attached 
+
+      // only add this display to the form if it is attached
       $display_options = $display->display_options;
       if(strcmp($display_options['displays'][$current_display],$current_display)!=0){
          continue;
-      } 
+      }
 
       // set the first item as default
       if (!$default) {

+ 1 - 1
tripal_views/tripal_views_integration.inc

@@ -606,7 +606,7 @@ function tripal_views_integration_form(&$form_state, $setup_id = NULL) {
       $default_join_handler = 0;
       if (isset($setup_id) && !isset($form_state['storage']["fields_join_handler_$table_id-$i"])) {
         $default_join_handler = $default_handlers[$column_name]['join']['handler_name'];
-        $form_state['storage']["fields_join_handler_$table_id-$i"]=$default_join_handler;
+        $form_state['storage']["fields_join_handler_$table_id-$i"] = $default_join_handler;
       }
       else {
         $default_join_handler = $form_state['storage']["fields_join_handler_$table_id-$i"];

+ 26 - 0
tripal_views/views/handlers/chado_views_handler_field_boolean.inc

@@ -85,6 +85,32 @@ class chado_views_handler_field_boolean extends views_handler_field_boolean {
    *   The values retrieved from the database.
    */
   function render($values) {
+
+    // check to see if this is a t/f boolean field or a 1/0 boolean field
+    // parent render expects 1/0 so need to translate to that form before rendering
+    if (!is_array($values->{$this->field_alias})) {
+      if (!preg_match('/[01]/',$values->{$this->field_alias})) {
+        if (preg_match('/^[tT]/',$values->{$this->field_alias})) {
+          $values->{$this->field_alias} = 1;
+        }
+        elseif (preg_match('/^[fF]/',$values->{$this->field_alias})) {
+          $values->{$this->field_alias} = 0;
+        }
+      }
+    }
+    else {
+      if (!preg_match('/[01]/',$values->{$this->field_alias}[0])) {
+        foreach ($values->{$this->field_alias} as $k => $v) {
+          if (preg_match('/^[tT]/',$v)) {
+            $values->{$this->field_alias}[$k] = 1;
+          }
+          elseif (preg_match('/^[fF]/',$v)) {
+            $values->{$this->field_alias}[$k] = 0;
+          }
+        }
+      }
+    }
+
     return chado_wrapper_render_items($this, $values);
   }
 

+ 16 - 0
tripal_views/views/handlers/chado_views_handler_field_date.inc

@@ -85,6 +85,22 @@ class chado_views_handler_field_date extends views_handler_field_date {
    *   The values retrieved from the database.
    */
   function render($values) {
+
+    // Check the format of the date is a UNIX timestamp and otherwise convert
+    if (!is_array($values->{$this->field_alias})) {
+      if (!preg_match('/^\d+$/',$values->{$this->field_alias})) {
+         $values->{$this->field_alias} = strtotime($values->{$this->field_alias});
+      }
+    }
+    else {
+      if (!preg_match('/^\d+$/',$values->{$this->field_alias}[0])) {
+        foreach ($values->{$this->field_alias} as $k => $v) {
+         $values->{$this->field_alias}[$k] = strtotime($v);
+        }
+      }
+    }
+
+    // render the items
     return chado_wrapper_render_items($this, $values);
   }
 

+ 55 - 6
tripal_views/views/handlers/chado_views_handler_filter_boolean_operator.inc

@@ -30,14 +30,14 @@ class chado_views_handler_filter_boolean_operator extends views_handler_filter_b
       '#type' => 'checkbox',
       '#title' => t('Filter base table records'),
       '#description' => t('Filters %base_table to only those with the value in the aggregate array.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['records_with'])) ? $this->options['records_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['records_with'])) ? $this->options['agg']['records_with'] : TRUE,
     );
 
     $form['agg']['aggregates_with'] = array(
       '#type' => 'checkbox',
       '#title' => t('Filter aggregates displayed'),
       '#description' => t('Filters the aggregates shown based on the value. Doesn\'t affect the number of %base_table records.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['aggregates_with'])) ? $this->options['aggregates_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['aggregates_with'])) ? $this->options['agg']['aggregates_with'] : TRUE,
     );
 
   }
@@ -50,12 +50,13 @@ class chado_views_handler_filter_boolean_operator extends views_handler_filter_b
 
     // make optional
     // if it is not set or empty then don't restrict the query
-    if (!$this->value) {
+    if ($this->value == 'All') {
       return;
     }
 
     $this->ensure_my_table();
 
+    // determine whether it is aggregated or not
     $table = $this->query->get_table_info($this->table);
     if (preg_match('/aggregator/', $table['join']->definition['handler'])) {
       $this->aggregated = TRUE;
@@ -64,8 +65,46 @@ class chado_views_handler_filter_boolean_operator extends views_handler_filter_b
       $this->aggregated = FALSE;
     }
 
+    // check if its a t/f or 1/0 boolean
+    $check = db_fetch_object(db_query("SELECT %s as val FROM %s LIMIT 1", $this->real_field, $this->table));
+    if (preg_match('/^[tTfF]/',$check->val)) {
+      $true = 't';
+      $false = 'f';
+    }
+    else {
+      $true = 1;
+      $false = 0;
+    }
+
     if (!$this->aggregated) {
-      parent::query();
+
+      // Only base records with value in the aggregated field
+      // This doesn't restrict the items in the aggregate field
+      if ($this->options['agg']['records_with']) {
+        $where = "$this->table_alias.$this->real_field ";
+        if (empty($this->value)) {
+          $where .= "= '".$false."'";
+          if ($this->accept_null) {
+            $where = '(' . $where . " OR $this->table_alias.$this->real_field IS NULL)";
+          }
+        }
+        else {
+          if (!empty($this->definition['use equal'])) {
+            $where .= "= '".$true."'";
+          }
+          else {
+            $where .= "<> '".$false."'";
+          }
+        }
+        $this->query->add_where($this->options['group'], $where);
+      }
+
+      // To restrict the items in the aggregate...
+      // Tell the join handler about the filter
+      // so it can be done in the join query
+      if ($this->options['agg']['aggregates_with']) {
+        //Do nothing b/c it's not aggregated!
+      }
     }
     else {
 
@@ -75,14 +114,24 @@ class chado_views_handler_filter_boolean_operator extends views_handler_filter_b
       $field = "$this->table_alias.$this->real_field";
       if ($this->options['agg']['records_with']) {
         $where = "'%s' = ANY($field)";
-        $this->query->add_where($this->options['group'], $where, $this->value);
+        if ($this->value) {
+          $this->query->add_where($this->options['group'], $where, $true);
+        }
+        else {
+          $this->query->add_where($this->options['group'], $where, $false);
+        }
       }
 
       // To restrict the items in the aggregate...
       // Tell the join handler about the filter
       // so it can be done in the join query
       if ($this->options['agg']['aggregates_with']) {
-        $table['join']->filter[] = $field . " = '" . $this->value . "'";
+        if ($this->value) {
+          $table['join']->filter[] = $field . " = '" . $true . "'";
+        }
+        else {
+          $table['join']->filter[] = $field . " = '" . $false . "'";
+        }
       }
     }
 

+ 97 - 29
tripal_views/views/handlers/chado_views_handler_filter_date.inc

@@ -7,6 +7,8 @@
  * Handles fields which may be aggregated during the chado join process. There are options
  * to filter the base table based on an aggregated table or just filter the aggregated
  * table (showing blank for that field if there are no records in the aggregated table).
+ *
+ * @todo make handle aggregation
  */
 class chado_views_handler_filter_date extends views_handler_filter_date {
 
@@ -30,62 +32,128 @@ class chado_views_handler_filter_date extends views_handler_filter_date {
       '#type' => 'checkbox',
       '#title' => t('Filter base table records'),
       '#description' => t('Filters %base_table to only those with the value in the aggregate array.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['records_with'])) ? $this->options['records_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['records_with'])) ? $this->options['agg']['records_with'] : TRUE,
     );
 
     $form['agg']['aggregates_with'] = array(
       '#type' => 'checkbox',
       '#title' => t('Filter aggregates displayed'),
       '#description' => t('Filters the aggregates shown based on the value. Doesn\'t affect the number of %base_table records.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['aggregates_with'])) ? $this->options['aggregates_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['aggregates_with'])) ? $this->options['agg']['aggregates_with'] : TRUE,
     );
 
   }
 
   /**
-   * If the table to be filtered is not aggregated uses the parent::query()
-   * However, if it is uses postgresql any() function to compare
+   * Called by query if the operator is between
    */
-  function query() {
+  function op_between($field) {
 
-    // make optional
-    // if it is not set or empty then don't restrict the query
-    if (!$this->value) {
-      return;
+    // Check whether we have a UNIX timestamp or an ISO Timestamp
+    $check = db_fetch_object(db_query("SELECT $this->real_field as val FROM $this->table WHERE $this->real_field IS NOT NULL LIMIT 1"));
+    if (preg_match('/^\d+$/',$check->val)) {
+      // this is a unix timestamp
+      $is_unix = TRUE;
+    }
+    else {
+      // this is an ISO Timestamp
+      $is_unix = FALSE;
     }
 
-    $this->ensure_my_table();
+    if ($this->operator == 'between') {
+      $a = intval(strtotime($this->value['min'], 0));
+      $b = intval(strtotime($this->value['max'], 0));
+    }
+    else {
+      $a = intval(strtotime($this->value['max'], 0));
+      $b = intval(strtotime($this->value['min'], 0));
+    }
 
-    $table = $this->query->get_table_info($this->table);
-    if (preg_match('/aggregator/', $table['join']->definition['handler'])) {
-      $this->aggregated = TRUE;
+    if ($this->value['type'] == 'offset') {
+      $a = '***CURRENT_TIME***' . sprintf('%+d', $a); // keep sign
+      $b = '***CURRENT_TIME***' . sprintf('%+d', $b); // keep sign
+    }
+    // %s is safe here because strtotime scrubbed the input and we might
+    // have a string if using offset.
+    if ($is_unix) {
+      if ($this->operator == 'between') {
+        $this->query->add_where($this->options['group'], "$field >= %s", $a);
+        $this->query->add_where($this->options['group'], "$field <= %s", $b);
+      }
+      else {
+        $this->query->add_where($this->options['group'], "$field >= %s OR $field <= %s", array($a, $b));
+      }
     }
     else {
-      $this->aggregated = FALSE;
+      if ($this->operator == 'between') {
+        $this->query->add_where($this->options['group'], "CAST(EXTRACT(EPOCH FROM $field) as integer) >= %s", $a);
+        $this->query->add_where($this->options['group'], "CAST(EXTRACT(EPOCH FROM $field) as integer) <= %s", $b);
+      }
+      else {
+        $this->query->add_where($this->options['group'], "CAST(EXTRACT(EPOCH FROM $field) as integer) >= %s OR CAST(EXTRACT(EPOCH FROM $field) as integer) <= %s", array($a, $b));
+      }
     }
+  }
 
-    if (!$this->aggregated) {
-      parent::query();
+  /**
+   * Called by query if the operator is not between or empty
+   */
+  function op_simple($field) {
+    $value = intval(strtotime($this->value['value'], 0));
+
+    // Check whether we have a UNIX timestamp or an ISO Timestamp
+    $check = db_fetch_object(db_query("SELECT $this->real_field as val FROM $this->table WHERE $this->real_field IS NOT NULL LIMIT 1"));
+    if (preg_match('/^\d+$/',$check->val)) {
+      // this is a unix timestamp
+      $is_unix = TRUE;
     }
     else {
+      // this is an ISO Timestamp
+      $is_unix = FALSE;
+    }
 
-      // Only base records with value in the aggregated field
-      // This doesn't restrict the items in the aggregate field
-      $this->ensure_my_table();
-      $field = "$this->table_alias.$this->real_field";
-      if ($this->options['agg']['records_with']) {
-        $where = "'%s' = ANY($field)";
-        $this->query->add_where($this->options['group'], $where, $this->value);
+    if ($is_unix) {
+      if (!empty($this->value['type']) && $this->value['type'] == 'offset') {
+        $value = '***CURRENT_TIME***' . sprintf('%+d', $value); // keep sign
       }
-
-      // To restrict the items in the aggregate...
-      // Tell the join handler about the filter
-      // so it can be done in the join query
-      if ($this->options['agg']['aggregates_with']) {
-        $table['join']->filter[] = $field . " = '" . $this->value . "'";
+      $this->query->add_where($this->options['group'], "$field $this->operator %s", $value);
+    }
+    else {
+      if (!empty($this->value['type']) && $this->value['type'] == 'offset') {
+        $value = '***CURRENT_TIME***' . sprintf('%+d', $value); // keep sign
       }
+      $this->query->add_where($this->options['group'], "CAST(EXTRACT(EPOCH FROM $field) as integer) $this->operator %s", $value);
     }
+  }
 
+  /**
+   * Validate that the time values convert to something usable.
+   *
+   * We modify it to
+   * - fix a bug in the views handler for single values
+   *    $value['value'] didn't exist
+   * - fix a pass by reference error
+   *    changed form_error to form_set_error
+   */
+  function validate_valid_time(&$form, $operator, $value) {
+    $operators = $this->operators();
+
+    if ($operators[$operator]['values'] == 1) {
+      $convert = strtotime($value);
+      if (!empty($form) && ($convert == -1 || $convert === FALSE)) {
+        form_set_error($form['value'], t('Invalid date format.'));
+      }
+    }
+    elseif ($operators[$operator]['values'] == 2) {
+      $min = strtotime($value['min']);
+      if ($min == -1 || $min === FALSE) {
+        form_set_error($form['min'], t('Invalid date format.'));
+      }
+      $max = strtotime($value['max']);
+      if ($max == -1 || $max === FALSE) {
+        form_set_error($form['max'], t('Invalid date format.'));
+      }
+    }
   }
 
 }

+ 2 - 2
tripal_views/views/handlers/chado_views_handler_filter_equality.inc

@@ -30,14 +30,14 @@ class chado_views_handler_filter_equality extends views_handler_filter_equality
       '#type' => 'checkbox',
       '#title' => t('Filter base table records'),
       '#description' => t('Filters %base_table to only those with the value in the aggregate array.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['records_with'])) ? $this->options['records_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['records_with'])) ? $this->options['agg']['records_with'] : TRUE,
     );
 
     $form['agg']['aggregates_with'] = array(
       '#type' => 'checkbox',
       '#title' => t('Filter aggregates displayed'),
       '#description' => t('Filters the aggregates shown based on the value. Doesn\'t affect the number of %base_table records.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['aggregates_with'])) ? $this->options['aggregates_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['aggregates_with'])) ? $this->options['agg']['aggregates_with'] : TRUE,
     );
 
   }

+ 2 - 2
tripal_views/views/handlers/chado_views_handler_filter_float.inc

@@ -30,14 +30,14 @@ class chado_views_handler_filter_float extends views_handler_filter_float {
       '#type' => 'checkbox',
       '#title' => t('Filter base table records'),
       '#description' => t('Filters %base_table to only those with the value in the aggregate array.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['records_with'])) ? $this->options['records_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['records_with'])) ? $this->options['agg']['records_with'] : TRUE,
     );
 
     $form['agg']['aggregates_with'] = array(
       '#type' => 'checkbox',
       '#title' => t('Filter aggregates displayed'),
       '#description' => t('Filters the aggregates shown based on the value. Doesn\'t affect the number of %base_table records.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['aggregates_with'])) ? $this->options['aggregates_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['aggregates_with'])) ? $this->options['agg']['aggregates_with'] : TRUE,
     );
 
   }

+ 2 - 2
tripal_views/views/handlers/chado_views_handler_filter_numeric.inc

@@ -30,14 +30,14 @@ class chado_views_handler_filter_numeric extends views_handler_filter_numeric {
       '#type' => 'checkbox',
       '#title' => t('Filter base table records'),
       '#description' => t('Filters %base_table to only those with the value in the aggregate array.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['records_with'])) ? $this->options['records_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['records_with'])) ? $this->options['agg']['records_with'] : TRUE,
     );
 
     $form['agg']['aggregates_with'] = array(
       '#type' => 'checkbox',
       '#title' => t('Filter aggregates displayed'),
       '#description' => t('Filters the aggregates shown based on the value. Doesn\'t affect the number of %base_table records.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['aggregates_with'])) ? $this->options['aggregates_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['aggregates_with'])) ? $this->options['agg']['aggregates_with'] : TRUE,
     );
 
   }

+ 25 - 11
tripal_views/views/handlers/chado_views_handler_filter_boolean_operator_string.inc → tripal_views/views/handlers/chado_views_handler_filter_select_cvterm.inc

@@ -2,13 +2,26 @@
 
 /**
  * @file
- * A chado wrapper for the views_handler_filter_boolean_operator_string.
+ * Purpose: This Handler provides a select list for the type field
  *
- * Handles fields which may be aggregated during the chado join process. There are options
- * to filter the base table based on an aggregated table or just filter the aggregated
- * table (showing blank for that field if there are no records in the aggregated table).
+ *  NOTE: This handler only works when applied to the type_id field in the base_table of
+ *  this view.
+ *
+ * @ingroup views_filter_handlers
+ * @ingroup tripal_core
  */
-class chado_views_handler_filter_boolean_operator_string extends views_handler_filter_boolean_operator_string {
+class chado_views_handler_filter_select_cvterm extends views_handler_filter_chado_select_cvterm_name {
+
+ /**
+  * Executed when the field is added
+  * Determine which cv to limit the cvterms to
+  */
+  function init(&$view, $options) {
+
+    include_once('chado_wrapper_functions.inc');
+    parent::init($view, $options);
+
+  }
 
   /**
    * Defines the options form (form available to admin when they add a field to a view)
@@ -29,15 +42,15 @@ class chado_views_handler_filter_boolean_operator_string extends views_handler_f
     $form['agg']['records_with'] = array(
       '#type' => 'checkbox',
       '#title' => t('Filter base table records'),
-      '#description' => t('Filters %table to only those with the value in the aggregate array.', array('%table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['records_with'])) ? $this->options['records_with'] : TRUE,
+      '#description' => t('Filters %base_table to only those with the value in the aggregate array.', array('%base_table' => $this->view->base_table)),
+      '#default_value' => (isset($this->options['agg']['records_with'])) ? $this->options['agg']['records_with'] : TRUE,
     );
 
     $form['agg']['aggregates_with'] = array(
       '#type' => 'checkbox',
       '#title' => t('Filter aggregates displayed'),
-      '#description' => t('Filters the aggregates shown based on the value. Doesn\'t affect the number of %table records.', array('%table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['aggregates_with'])) ? $this->options['aggregates_with'] : TRUE,
+      '#description' => t('Filters the aggregates shown based on the value. Doesn\'t affect the number of %base_table records.', array('%base_table' => $this->view->base_table)),
+      '#default_value' => (isset($this->options['agg']['aggregates_with'])) ? $this->options['agg']['aggregates_with'] : TRUE,
     );
 
   }
@@ -82,10 +95,11 @@ class chado_views_handler_filter_boolean_operator_string extends views_handler_f
       // Tell the join handler about the filter
       // so it can be done in the join query
       if ($this->options['agg']['aggregates_with']) {
-        $table['join']->filter[] = $field . " = '" . $this->value . "'";
+        if (sizeof($this->value) == 1) {
+          $table['join']->filter[] = $field . " = '" . array_pop($this->value) . "'";
+        }
       }
     }
 
   }
-
 }

+ 364 - 0
tripal_views/views/handlers/chado_views_handler_filter_select_string.inc

@@ -0,0 +1,364 @@
+<?php
+
+/**
+ * @file
+ * Purpose: This Handler provides a generic select list for any chado field that is a string
+ *  The select list includes all distinct values for that field.
+ *
+ * @ingroup views_filter_handlers
+ * @ingroup tripal_core
+ */
+class chado_views_handler_filter_select_string extends chado_views_handler_filter_string {
+
+  function options_form(&$form, &$form_state) {
+    parent::options_form($form, $form_state);
+
+    $form['values_form_type'] = array(
+      '#type' => 'radios',
+      '#title' => t('Filter Type'),
+      '#options' => array(
+        'textfield' => 'Text Field',
+        'select' => 'Drop-Down Box',
+      ),
+      '#default_value' => ($this->options['values_form_type']) ? $this->options['values_form_type'] : 'select',
+    );
+
+    $form['multiple'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Select Multiple'),
+      '#description' => t('Allows more then one option to be selected.'),
+      '#default_value' => (isset($this->options['multiple'])) ? $this->options['multiple'] : FALSE,
+    );
+
+    $form['optional'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Optional'),
+      '#description' => t('Adds --Any-- to the available options.'),
+      '#default_value' => (isset($this->options['optional'])) ? $this->options['optional'] : TRUE,
+    );
+
+    $form['max_length'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Max Width'),
+      '#description' => t('Specify the maximum width of the select box'),
+      '#default_value' => (isset($this->options['max_length'])) ? $this->options['max_length'] : 40,
+
+    );
+    $form['max_length'] = array(
+      '#type' => 'markup',
+      '#value' => t('<strong><font color="red">Note:</font></strong> If another filter exists for the same table then '.
+                    'the values shown in the drop box will only include those from rows that are not filtered.'),
+
+    );
+
+  }
+
+ /**
+  * Defines the value field in both the views filter options form
+  *   and the exposed form
+  */
+  function value_form(&$form, &$form_state) {
+    parent::value_form($form, $form_state);
+
+    if (preg_match('/textfield/', $this->options['values_form_type'])) {
+      $form['value'] = array(
+        '#type' => 'textfield',
+        '#title' => t('%label', array('%label' => $this->options['label'])),
+        '#default_value' => $this->value,
+      );
+
+    }
+    else {
+
+      // build a where clause that will filter the list in the drop box
+      // using fields that are not exposed and that are for the table
+      // from whcih the values in the drop box will be slected and
+      // we only want to use non-exposed fields because these are not
+      // available to the user to edit--their fixed.
+      $where = '';
+      $filters = ($this->view->filter) ? $this->view->filter : array();
+      foreach($filters as $filter_name => $details){
+         // we only want to inclue non-exposed filters
+         if($details->options['exposed'] == FALSE){
+            // we only want to filter on the table we're getting the list from
+            if(strcmp($details->table,$this->table)==0){
+              $where .= "$details->field $details->operator ". $details->value['value'];
+              $where .= ' AND ';
+            }
+         }
+      }
+      if($where){
+         $where = "WHERE $where";
+         $where = substr($where,0,-5); # remove the final ' AND '
+      }
+
+      // get the values from the table
+      $sql = "SELECT $this->real_field FROM $this->table $where ORDER BY $this->field ASC";
+      $previous_db = tripal_db_set_active('chado');  // use chado database
+      $results = db_query($sql);
+      tripal_db_set_active($previous_db);  // now use drupal database
+
+      // Build the select box options
+      $max_length = $this->options['max_length'];
+      if (!$max_length) {
+        $max_length = 40;
+      }
+      if ($this->options['optional']) {
+        //$options['<select '.$this->table.'>'] = '--None--';
+        $options['All'] = '--Any--';
+      }
+      while ($r = db_fetch_object($results)) {
+        if (drupal_strlen($r->{$this->field}) > $max_length) {
+          $options[$r->{$this->field}] = drupal_substr($r->{$this->field}, 0, $max_length) . '...';
+        }
+        else {
+          $options[$r->{$this->field}] = $r->{$this->field};
+        }
+      }
+
+      //Select List
+      $form['value'] = array(
+          '#type' => 'select',
+          '#title' => t('%label', array('%label' => $this->options['label'])),
+          '#options' => $options,
+          '#default_value' => $this->value,
+      );
+
+      if ($this->options['multiple']) {
+        $form['value']['#multiple'] = TRUE;
+      }
+    }
+  }
+
+ /**
+  * Ensures the select list gets rendered when the filter is exposed
+  */
+  function exposed_form(&$form, &$form_state) {
+    if (empty($this->options['exposed'])) {
+      return;
+    }
+
+    $value = $this->options['expose']['identifier'];
+    $this->value_form($form, $form_state);
+    $form[$value] = $form['value'];
+
+    if (isset($form[$value]['#title']) && !empty($form[$value]['#type']) && $form[$value]['#type'] != 'checkbox') {
+      unset($form[$value]['#title']);
+    }
+
+    $this->exposed_translate($form[$value], 'value');
+
+    if (!empty($form['#type']) && ($form['#type'] == 'checkboxes' || ($form['#type'] == 'select' && !empty($form['#multiple'])))) {
+      unset($form[$value]['#default_value']);
+    }
+
+    if (!empty($form['#type']) && $form['#type'] == 'select' && empty($form['#multiple'])) {
+      $form[$value]['#default_value'] = 'All';
+    }
+
+    if ($value != 'value') {
+      unset($form['value']);
+    }
+
+  }
+
+ /**
+  * Adds this filter to the where clause of the views query
+  */
+  function query() {
+
+    // make optional
+    // if it is not set or empty then don't restrict the query
+    if (!$this->value) {
+      return;
+    }
+
+    $this->ensure_my_table();
+
+    $table = $this->query->get_table_info($this->table);
+    if (preg_match('/aggregator/', $table['join']->definition['handler'])) {
+      $this->aggregated = TRUE;
+    }
+    else {
+      $this->aggregated = FALSE;
+    }
+
+    // filter the aggregates
+    if ($this->options['agg']['aggregates_with']) {
+      $this::query_restrict_curr_table_records();
+    }
+
+    // filter the base table
+    if ($this->options['agg']['records_with']) {
+      $this::query_restrict_base_records();
+    }
+
+
+
+
+  }
+
+  /**
+   * This function alters the query by adding the appropriate WHERE
+   * to filter the base table to only those with the value in the aggregate array.
+   *
+   * Note: this function is called only from query()
+   */
+  function query_restrict_base_records() {
+    if (!$this->aggregated) {
+      // Not Aggregated ---------------
+
+      $this->ensure_my_table();
+      $field = "$this->table_alias.$this->real_field";
+      $upper = $this->case_transform();
+
+      if ($this->options['multiple'] AND is_array($this->value)) {
+        // Remove any if it's there
+        unset($this->value['All']);
+
+        if (sizeof($this->value)) {
+          $holders = array();
+          foreach ($this->value as $v) {
+            if (preg_match('/^[\d\.]+$/', $v)) {
+              $holders[] = '%f';
+            }
+            else {
+              $holders[] = "'%s'";
+            }
+          }
+          $where = "$field IN (" . implode(", ", $holders) . ")";
+          $this->query->add_where($this->options['group'], $where, $this->value);
+        }
+      }
+      else {
+
+        // Deal with All/Any as value
+        if (preg_match('/All/', $this->value)) {
+          // Don't do anything
+        }
+        else {
+          $info = $this->operators();
+          if (!empty($info[$this->operator]['method'])) {
+            $this->{$info[$this->operator]['method']}($field, $upper);
+          }
+        }
+      }
+
+    }
+    else {
+      // Is Aggregated ----------------
+
+      $this->ensure_my_table();
+      $field = "$this->table_alias.$this->real_field";
+      $upper = $this->case_transform();
+
+      if ($this->options['multiple'] AND is_array($this->value)) {
+        // Remove any if it's there
+        unset($this->value['All']);
+
+        if (sizeof($this->value) > 1) {
+          $holders = array();
+          foreach ($this->value as $v) {
+            $holders[] = "'%s'";
+          }
+          $where = $field .' && ARRAY[' . implode(", ", $holders) . ']';
+          $this->query->add_where($this->options['group'], $where, $this->value);
+
+        }
+        elseif (sizeof($this->value) == 1) {
+          $where = "'%s' = ANY($field)";
+          $this->query->add_where($this->options['group'], $where, array_pop($this->value));
+        }
+      }
+      else {
+
+        // Deal with All/Any as value
+        if (preg_match('/All/', $this->value)) {
+          // Don't do anything
+        }
+        else {
+          $where = "'%s' = ANY($field)";
+          $this->query->add_where($this->options['group'], $where, $this->value);
+        }
+      }
+
+    }
+  }
+
+  /**
+   * This function alters the query by adding the appropriate WHERE
+   * to filter the aggregates shown based on the value. Doesn't affect
+   * the number of base table records.
+   *
+   * Note: this function is called only from query()
+   */
+  function query_restrict_curr_table_records() {
+
+    if (!$this->aggregated) {
+      // Not Aggregated ---------------
+      // Warn the admin/user that they have selected that the aggregates should be filtered
+      // on a field that isn't aggregated...
+      watchdog(
+        'tripal_views',
+        'You have chosen to filter the aggregates shown for %table %field
+          in %view; however, that field is not aggregated (ie: it is part of the base table
+          or is a 1:1 relationship to the base table)',
+        array(
+          '%field' => $this->field,
+          '%table' => $this->table,
+          '%view' => $this->view->name
+        ),
+        WATCHDOG_WARNING
+      );
+      // Do nothing!
+    }
+    else {
+      // Is Aggregated ----------------
+
+      $this->ensure_my_table();
+      $field = "$this->table_alias.$this->real_field";
+      $upper = $this->case_transform();
+
+      if ($this->options['multiple'] AND is_array($this->value)) {
+        // Remove any if it's there
+        unset($this->value['All']);
+
+        if (sizeof($this->value) > 1) {
+          $holders = array();
+          foreach ($this->value as $v) {
+            $holders[] = "'%s'";
+          }
+          $where = $field .' IN (' . implode(", ", $holders) . ')';
+          $where = vsprintf($where, $this->value);
+
+          // Add the where to the chado aggregated join object for this table
+          // then the views_handler_join_chado_aggregator will add this to the WHERE
+          // clause of the sub-query generating the aggregated listing
+          $this->query->table_queue[ $this->table ]['join']->filter[] = $where;
+
+        }
+        elseif (sizeof($this->value) == 1) {
+          $where = "$field = '%s'";
+          $where = vsprintf($where, $this->value);
+
+          // Add the where to the chado aggregated join object for this table
+          // then the views_handler_join_chado_aggregator will add this to the WHERE
+          // clause of the sub-query generating the aggregated listing
+          $this->query->table_queue[ $this->table ]['join']->filter[] = $where;
+        }
+      }
+      else {
+
+        // Deal with All/Any as value
+        if (preg_match('/All/', $this->value)) {
+          // Don't do anything
+        }
+        else {
+          $where = "'%s' = ANY($field)";
+          $this->query->add_where($this->options['group'], $where, $this->value);
+        }
+      }
+
+    }
+  }
+}

+ 2 - 2
tripal_views/views/handlers/chado_views_handler_filter_string.inc

@@ -30,14 +30,14 @@ class chado_views_handler_filter_string extends views_handler_filter_string {
       '#type' => 'checkbox',
       '#title' => t('Filter base table records'),
       '#description' => t('Filters %base_table to only those with the value in the aggregate array.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['records_with'])) ? $this->options['records_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['records_with'])) ? $this->options['agg']['records_with'] : TRUE,
     );
 
     $form['agg']['aggregates_with'] = array(
       '#type' => 'checkbox',
       '#title' => t('Filter aggregates displayed'),
       '#description' => t('Filters the aggregates shown based on the value. Doesn\'t affect the number of %base_table records.', array('%base_table' => $this->view->base_table)),
-      '#default_value' => (isset($this->options['aggregates_with'])) ? $this->options['aggregates_with'] : TRUE,
+      '#default_value' => (isset($this->options['agg']['aggregates_with'])) ? $this->options['agg']['aggregates_with'] : TRUE,
     );
 
   }

+ 0 - 58
tripal_views/views/handlers/chado_views_handler_sort_date.inc

@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * A chado wrapper for the views_handler_sort_date.
- *
- * Handles fields which may be aggregated during the chado join process. Sorting of
- * aggregated fields required PostgreSQL 9.0 due to postgresql limitations. Sorting of
- * non-aggregated fields works for all PostgreSQL versions.
- */
-class chado_views_handler_sort extends views_handler_sort_date {
-
-  /**
-   * Defines the options form (form available to admin when they add a field to a view)
-   */
-  function options_form(&$form, &$form_state) {
-
-    $form['msg'] = array(
-      '#type' => 'item',
-      '#value' => '<b>Sorting of aggregated fields only works for PostgreSQL 9.0+. This is due to lack of support at the database level. With lower postgreSQL versions, no sorting is applied.</b>'
-    );
-
-    parent::options_form($form, $form_state);
-  }
-
-  /**
-   * Adds the sort to the query only if the field isn't aggregated
-   * If the field is aggregated then the sort has to be applied at the join handler level
-   */
-  function query() {
-
-    // Determine if the current field is part of an aggregated table
-    $table = $this->query->get_table_info($this->table);
-    if (preg_match('/aggregator/', $table['join']->definition['handler'])) {
-      $this->aggregated = TRUE;
-    }
-    else {
-      $this->aggregated = FALSE;
-    }
-
-    // One day when the aggregated sort will work (ie: Postgresql 9.0+)
-    // it will need to be applied in join handler
-    // thus tell join handler about the sort
-    $table['join']->sort[] = array(
-      'table' => $table['alias'],
-      'field' => $this->options['field'],
-      'order' => $this->options['order']
-    );
-
-
-    // if not then add the sort
-    if (!$this->aggregated) {
-      parent::query();
-    }
-
-  }
-
-}

+ 0 - 58
tripal_views/views/handlers/chado_views_handler_sort_formula.inc

@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * A chado wrapper for the views_handler_sort_formula.
- *
- * Handles fields which may be aggregated during the chado join process. Sorting of
- * aggregated fields required PostgreSQL 9.0 due to postgresql limitations. Sorting of
- * non-aggregated fields works for all PostgreSQL versions.
- */
-class chado_views_handler_sort extends views_handler_sort_formula {
-
-  /**
-   * Defines the options form (form available to admin when they add a field to a view)
-   */
-  function options_form(&$form, &$form_state) {
-
-    $form['msg'] = array(
-      '#type' => 'item',
-      '#value' => '<b>Sorting of aggregated fields only works for PostgreSQL 9.0+. This is due to lack of support at the database level. With lower postgreSQL versions, no sorting is applied.</b>'
-    );
-
-    parent::options_form($form, $form_state);
-  }
-
-  /**
-   * Adds the sort to the query only if the field isn't aggregated
-   * If the field is aggregated then the sort has to be applied at the join handler level
-   */
-  function query() {
-
-    // Determine if the current field is part of an aggregated table
-    $table = $this->query->get_table_info($this->table);
-    if (preg_match('/aggregator/', $table['join']->definition['handler'])) {
-      $this->aggregated = TRUE;
-    }
-    else {
-      $this->aggregated = FALSE;
-    }
-
-    // One day when the aggregated sort will work (ie: Postgresql 9.0+)
-    // it will need to be applied in join handler
-    // thus tell join handler about the sort
-    $table['join']->sort[] = array(
-      'table' => $table['alias'],
-      'field' => $this->options['field'],
-      'order' => $this->options['order']
-    );
-
-
-    // if not then add the sort
-    if (!$this->aggregated) {
-      parent::query();
-    }
-
-  }
-
-}

+ 0 - 58
tripal_views/views/handlers/chado_views_handler_sort_menu_hierarchy.inc

@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * A chado wrapper for the views_handler_sort_menu_hierarchy.
- *
- * Handles fields which may be aggregated during the chado join process. Sorting of
- * aggregated fields required PostgreSQL 9.0 due to postgresql limitations. Sorting of
- * non-aggregated fields works for all PostgreSQL versions.
- */
-class chado_views_handler_sort extends views_handler_sort_menu_hierarchy {
-
-  /**
-   * Defines the options form (form available to admin when they add a field to a view)
-   */
-  function options_form(&$form, &$form_state) {
-
-    $form['msg'] = array(
-      '#type' => 'item',
-      '#value' => '<b>Sorting of aggregated fields only works for PostgreSQL 9.0+. This is due to lack of support at the database level. With lower postgreSQL versions, no sorting is applied.</b>'
-    );
-
-    parent::options_form($form, $form_state);
-  }
-
-  /**
-   * Adds the sort to the query only if the field isn't aggregated
-   * If the field is aggregated then the sort has to be applied at the join handler level
-   */
-  function query() {
-
-    // Determine if the current field is part of an aggregated table
-    $table = $this->query->get_table_info($this->table);
-    if (preg_match('/aggregator/', $table['join']->definition['handler'])) {
-      $this->aggregated = TRUE;
-    }
-    else {
-      $this->aggregated = FALSE;
-    }
-
-    // One day when the aggregated sort will work (ie: Postgresql 9.0+)
-    // it will need to be applied in join handler
-    // thus tell join handler about the sort
-    $table['join']->sort[] = array(
-      'table' => $table['alias'],
-      'field' => $this->options['field'],
-      'order' => $this->options['order']
-    );
-
-
-    // if not then add the sort
-    if (!$this->aggregated) {
-      parent::query();
-    }
-
-  }
-
-}

+ 0 - 58
tripal_views/views/handlers/chado_views_handler_sort_random.inc

@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * A chado wrapper for the views_handler_sort_random.
- *
- * Handles fields which may be aggregated during the chado join process. Sorting of
- * aggregated fields required PostgreSQL 9.0 due to postgresql limitations. Sorting of
- * non-aggregated fields works for all PostgreSQL versions.
- */
-class chado_views_handler_sort extends views_handler_sort_random {
-
-  /**
-   * Defines the options form (form available to admin when they add a field to a view)
-   */
-  function options_form(&$form, &$form_state) {
-
-    $form['msg'] = array(
-      '#type' => 'item',
-      '#value' => '<b>Sorting of aggregated fields only works for PostgreSQL 9.0+. This is due to lack of support at the database level. With lower postgreSQL versions, no sorting is applied.</b>'
-    );
-
-    parent::options_form($form, $form_state);
-  }
-
-  /**
-   * Adds the sort to the query only if the field isn't aggregated
-   * If the field is aggregated then the sort has to be applied at the join handler level
-   */
-  function query() {
-
-    // Determine if the current field is part of an aggregated table
-    $table = $this->query->get_table_info($this->table);
-    if (preg_match('/aggregator/', $table['join']->definition['handler'])) {
-      $this->aggregated = TRUE;
-    }
-    else {
-      $this->aggregated = FALSE;
-    }
-
-    // One day when the aggregated sort will work (ie: Postgresql 9.0+)
-    // it will need to be applied in join handler
-    // thus tell join handler about the sort
-    $table['join']->sort[] = array(
-      'table' => $table['alias'],
-      'field' => $this->options['field'],
-      'order' => $this->options['order']
-    );
-
-
-    // if not then add the sort
-    if (!$this->aggregated) {
-      parent::query();
-    }
-
-  }
-
-}

+ 7 - 1
tripal_views/views/handlers/chado_wrapper_functions.inc

@@ -65,7 +65,13 @@ function chado_wrapper_is_aggregated_by_join($handler) {
 function chado_wrapper_is_aggregated_by_result($handler, $values) {
   $aggregated = FALSE;
 
-  if (preg_match('/^{.*}$/', $values[0]->{$handler->field_alias})) {
+
+  $i = 0;
+  while (empty($values[$i]->{$handler->field_alias}) AND $i <= sizeof($values)) {
+    $i++;
+  }
+
+  if (preg_match('/^{.*}$/', $values[$i]->{$handler->field_alias})) {
     $aggregated = TRUE;
   }
 

+ 0 - 39
tripal_views/views/handlers/views_handler_field_chado_tf_boolean.inc

@@ -1,39 +0,0 @@
-<?php
-
-/**
- * @file
- * A handler to provide proper displays for booleans.
- *
- * Allows for display of true/false, yes/no, on/off.
- *
- * Definition terms:
- *   - output formats: An array where the first entry is displayed on boolean false
- *      and the second is displayed on boolean true. An example for sticky is:
- *      @code
- *      'output formats' => array(
- *        'sticky' => array('', t('Sticky')),
- *      ),
- *      @endcode
- *
- * @ingroup views_field_handlers
- * @ingroup tripal_core
- */
-class views_handler_field_chado_tf_boolean extends views_handler_field_boolean {
-
-  // Changes the rendered value: t='Yes' & f='No'
-  // Rendered value depends on type of value chosen in options
-  function render($values) {
-    $value = $values->{$this->field_alias};
-    if (!empty($this->options['not'])) {
-      $value = !$value;
-    }
-
-    if (isset($this->formats[$this->options['type']])) {
-      return preg_match('/t/', $value) ? $this->formats[$this->options['type']][0] : $this->formats[$this->options['type']][1];
-    }
-    else {
-      return preg_match('/t/', $value) ? $this->formats['yes-no'][0] : $this->formats['yes-no'][1];
-    }
-  }
-
-}

+ 1 - 1
tripal_views/views/handlers/views_handler_filter_chado_select_cvterm_name.inc

@@ -61,7 +61,7 @@ class views_handler_filter_chado_select_cvterm_name extends views_handler_filter
       // @coder-ignore: non-drupal schema therefore table prefixing does not apply
       $sql = "SELECT cvterm_id, name FROM cvterm WHERE cvterm_id IN (SELECT distinct(type_id) FROM %s)";
       $previous_db = tripal_db_set_active('chado');
-      $resource = db_query($sql, $this->view->base_table);
+      $resource = db_query($sql, $this->table);
       tripal_db_set_active($previous_db);
       $cvterms = array();
       while ( $r = db_fetch_object($resource) ) {