From c87bebba6092916d76051a047f521766ffa75cb0 Mon Sep 17 00:00:00 2001
From: Dan Chadwick <dan899@gmail.com>
Date: Tue, 21 Apr 2015 11:05:12 -0400
Subject: [PATCH] Issue #2449871 by DanChadwick: Numeric display, comparison
 and sort of submitted data in views.

---
 views/webform.views.inc                |   24 +++++
 views/webform_handler_numeric_data.inc |  173 ++++++++++++++++++++++++++++++++
 webform.info                           |    5 +-
 3 files changed, 200 insertions(+), 2 deletions(-)
 create mode 100644 views/webform_handler_numeric_data.inc

diff --git a/views/webform.views.inc b/views/webform.views.inc
index 4713d2e..9590ae5 100644
--- a/views/webform.views.inc
+++ b/views/webform.views.inc
@@ -372,6 +372,30 @@ function webform_views_data() {
     ),
   );
 
+  // Same as 'data', but handled as numeric data.
+  $data['webform_submitted_data']['data_numeric'] = array(
+    'table' => 'webform_submitted_data',
+    'title' => t('Data field (numeric)'),
+    'help' => t('The numeric value of a component as submitted by a user.'),
+    'real field' => 'data',
+    'field' => array(
+      'title' => t('Numeric value (raw)'), // Distinguish from the normal value handler.
+      'help' => t('The raw value from the database, cast to a number, as submitted by a user. Use only when needing to sort on a field value.'),
+      'handler' => 'webform_handler_field_numeric_data',
+      'click sortable' => TRUE,
+      'float' => TRUE,
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_numeric',
+    ),
+    'filter' => array(
+      'handler' => 'webform_handler_filter_numeric_data',
+    ),
+    'sort' => array(
+      'handler' => 'webform_handler_sort_numeric_data',
+    ),
+  );
+
   // Number field for multi-value fields.
   $data['webform_submitted_data']['no'] = array(
     'title' => t('Value delta'),
diff --git a/views/webform_handler_numeric_data.inc b/views/webform_handler_numeric_data.inc
new file mode 100644
index 0000000..d3b15ba
--- /dev/null
+++ b/views/webform_handler_numeric_data.inc
@@ -0,0 +1,173 @@
+<?php
+
+/**
+ * @file
+ * Definition of handlers for using numeric submission data.
+ */
+
+/**
+ * Extended version of the numeric field handler specialized for Webform values.
+ *
+ * @ingroup views_field_handlers
+ */
+class webform_handler_field_numeric_data extends views_handler_field_numeric {
+
+  var $formula = NULL;
+
+  /**
+   * Constructor
+   */
+  function construct() {
+    parent::construct();
+    $this->formula = TRUE;
+  }
+  
+  /**
+   * Get the formula for this argument.
+   *
+   * $this->ensure_my_table() MUST have been called prior to this.
+   */
+  function get_formula() {
+    return ("(0.0 + $this->table_alias.$this->real_field)");
+  }
+
+  /**
+   * Called to add the field to a query.
+   */
+  function query() {
+    $this->ensure_my_table();
+    // Add the field.
+    $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array();
+    $this->field_alias = $this->query->add_field(NULL, $this->get_formula(), $this->table_alias . '_' . $this->field, $params);
+
+    $this->add_additional_fields();
+  }
+
+    /**
+   * Shortcut to get a handler's raw field value.
+   *
+   * This should be overridden for handlers with formulae or other
+   * non-standard fields. Because this takes an argument, fields
+   * overriding this can just call return parent::get_field($formula)
+   */
+  function get_field($field = NULL) {
+    return parent::get_field($this->get_formula());
+  }
+  
+}
+
+/**
+ * Numeric filter handler that works with Webform numeric submission data.
+ *
+ * @ingroup views_filter_handlers
+ */
+class webform_handler_filter_numeric_data extends views_handler_filter_numeric {
+
+  /**
+   * Get the formula for this argument.
+   *
+   * $this->ensure_my_table() MUST have been called prior to this.
+   */
+  function get_formula() {
+    return ("(0.0 + $this->table_alias.$this->real_field)");
+  }
+
+  /**
+   * Called to add the filter to a query.
+   */
+  function query() {
+    $this->ensure_my_table();
+
+    $info = $this->operators();
+    if (!empty($info[$this->operator]['method'])) {
+      $this->{$info[$this->operator]['method']}($this->get_formula());
+    }
+  }
+
+  /**
+   * Adds a simple operator condition to the query.
+   */
+  function op_simple($field) {
+    static $sequence = 1;
+    $param =  ":value" . $sequence++;
+    $this->query->add_where_expression($this->options['group'],
+                                       $field . $this->operator . $param,
+                                       array($param =>  $this->value['value']));
+  }
+
+  /**
+   * Adds a between or not-between condition to the query.
+   */
+  function op_between($field) {
+    static $sequence = 1;
+    $min =  ":min" . $sequence;
+    $max =  ":max" . $sequence++;
+    if ($this->operator == 'between') {
+      $this->query->add_where_expression($this->options['group'],
+                                         "($min <= $field AND $field <= $max)",
+                                         array($min => $this->value['min'], $max => $this->value['max']));
+    }
+    else {
+      $this->query->add_where_expression($this->options['group'],
+                                         "($min > $field OR $field > $max)",
+                                         array($min => $this->value['min'], $max => $this->value['max']));
+    }
+  }
+
+  /**
+   * Adds an empty or not-empty condition to the query.
+   */
+  function op_empty($field) {
+    if ($this->operator == 'empty') {
+      $operator = "IS NULL";
+    }
+    else {
+      $operator = "IS NOT NULL";
+    }
+
+    $this->query->add_where_expression($this->options['group'],
+                                       "$field $operator");
+  }
+
+  /**
+   * Adds a regular expression condition to the query.
+   */
+  function op_regex($field) {
+    static $sequence = 1;
+    $param =  ":expression" . $sequence++;
+
+    $this->query->add_where_expression($this->options['group'],
+                                       "$field RLIKE $param",
+                                       array($param => $this->value['value']));
+  }
+
+}
+
+/**
+ * Sort handler that works with Webform numeric submission data.
+ *
+ * @ingroup views_sort_handlers
+ */
+class webform_handler_sort_numeric_data extends views_handler_sort {
+
+  /**
+   * Get the formula for this sort.
+   *
+   * $this->ensure_my_table() MUST have been called prior to this.
+   */
+  function get_formula() {
+    return ("(0.0 + $this->table_alias.$this->real_field)");
+  }
+
+  /**
+   * Called to add the sort to a query.
+   */
+  function query() {
+    $this->ensure_my_table();
+    // Add the field.
+    $alias = $this->query->add_field(NULL, $this->get_formula(), $this->table_alias . '_' . $this->field . '_sort');
+    // Add the sort for the field using only the alias.
+    $this->query->add_orderby(NULL, NULL, $this->options['order'], $alias);
+  }
+
+}
diff --git a/webform.info b/webform.info
index cb53887..3371e69 100644
--- a/webform.info
+++ b/webform.info
@@ -17,6 +17,7 @@ files[] = includes/exporters/webform_exporter_excel_delimited.inc
 files[] = includes/exporters/webform_exporter_excel_xlsx.inc
 files[] = includes/exporters/webform_exporter.inc
 
+files[] = views/webform_handler_area_result_pager.inc
 files[] = views/webform_handler_field_form_body.inc
 files[] = views/webform_handler_field_is_draft.inc
 files[] = views/webform_handler_field_node_link_edit.inc
@@ -28,9 +29,9 @@ files[] = views/webform_handler_field_webform_status.inc
 files[] = views/webform_handler_filter_is_draft.inc
 files[] = views/webform_handler_filter_submission_data.inc
 files[] = views/webform_handler_filter_webform_status.inc
-files[] = views/webform_handler_area_result_pager.inc
-files[] = views/webform_plugin_row_submission_view.inc
+files[] = views/webform_handler_numeric_data.inc
 files[] = views/webform_handler_relationship_submission_data.inc
+files[] = views/webform_plugin_row_submission_view.inc
 files[] = views/webform.views.inc
 
 files[] = tests/components.test
-- 
1.7.8.msysgit.0

