From be844e07e8ef1bcbb3ff5caecfd95d48103e5016 Mon Sep 17 00:00:00 2001
From: Dan Chadwick <dan899@gmail.com>
Date: Fri, 10 Apr 2015 13:26:41 -0400
Subject: [PATCH] Issue #2450163 by DanChadwick: Filter analysis data with
 views.

---
 components/date.inc                      |   14 ++++--
 components/email.inc                     |   12 ++++--
 components/file.inc                      |   12 ++++--
 components/grid.inc                      |   20 ++++++----
 components/hidden.inc                    |   12 ++++--
 components/number.inc                    |   12 ++++--
 components/select.inc                    |   27 ++++++++-----
 components/textarea.inc                  |   12 ++++--
 components/textfield.inc                 |   12 ++++--
 components/time.inc                      |   14 ++++--
 includes/webform.report.inc              |   30 ++++++++++++++-
 templates/webform-analysis.tpl.php       |    4 ++
 views/default_views/webform_analysis.inc |   61 ++++++++++++++++++++++++++++++
 webform.api.php                          |    9 ++++-
 14 files changed, 196 insertions(+), 55 deletions(-)
 create mode 100644 views/default_views/webform_analysis.inc

diff --git a/components/date.inc b/components/date.inc
index 581f9f9..65853a6 100644
--- a/components/date.inc
+++ b/components/date.inc
@@ -381,15 +381,19 @@ function theme_webform_display_date($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_date($component, $sids = array()) {
+function _webform_analysis_date($component, $sids = array(), $single = FALSE, $join = NULL) {
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
     ->fields('wsd', array('no', 'data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid'])
-    ->orderBy('sid');
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid'])
+    ->orderBy('wsd.sid');
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $result = $query->execute();
diff --git a/components/email.inc b/components/email.inc
index feadb70..e1d5102 100644
--- a/components/email.inc
+++ b/components/email.inc
@@ -243,14 +243,18 @@ function theme_webform_display_email($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_email($component, $sids = array()) {
+function _webform_analysis_email($component, $sids = array(), $single = FALSE, $join = NULL) {
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
     ->fields('wsd', array('no', 'data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid']);
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid']);
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $nonblanks = 0;
diff --git a/components/file.inc b/components/file.inc
index 794d9b8..364a136 100644
--- a/components/file.inc
+++ b/components/file.inc
@@ -455,14 +455,18 @@ function _webform_attachments_file($component, $value) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_file($component, $sids = array()) {
+function _webform_analysis_file($component, $sids = array(), $single = FALSE, $join = NULL) {
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
     ->fields('wsd', array('no', 'data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid']);
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid']);
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $nonblanks = 0;
diff --git a/components/grid.inc b/components/grid.inc
index 93d101e..2ef65ff 100644
--- a/components/grid.inc
+++ b/components/grid.inc
@@ -349,7 +349,7 @@ function theme_webform_display_grid($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_grid($component, $sids = array()) {
+function _webform_analysis_grid($component, $sids = array(), $single = FALSE, $join = NULL) {
   // Generate the list of options and questions.
   $node = node_load($component['nid']);
   $questions = _webform_select_options_from_text($component['extra']['questions'], TRUE);
@@ -360,15 +360,19 @@ function _webform_analysis_grid($component, $sids = array()) {
   // Generate a lookup table of results.
   $query = db_select('webform_submitted_data', 'wsd')
     ->fields('wsd', array('no', 'data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid'])
-    ->condition('data', '', '<>')
-    ->groupBy('no')
-    ->groupBy('data');
-  $query->addExpression('COUNT(sid)', 'datacount');
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid'])
+    ->condition('wsd.data', '', '<>')
+    ->groupBy('wsd.no')
+    ->groupBy('wsd.data');
+  $query->addExpression('COUNT(wsd.sid)', 'datacount');
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $result = $query->execute();
diff --git a/components/hidden.inc b/components/hidden.inc
index 233cf87..4fef018 100644
--- a/components/hidden.inc
+++ b/components/hidden.inc
@@ -126,14 +126,18 @@ function theme_webform_display_hidden($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_hidden($component, $sids = array()) {
+function _webform_analysis_hidden($component, $sids = array(), $single = FALSE, $join = NULL) {
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
     ->fields('wsd', array('no', 'data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid']);
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid']);
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $nonblanks = 0;
diff --git a/components/number.inc b/components/number.inc
index 7383234..7950a13 100644
--- a/components/number.inc
+++ b/components/number.inc
@@ -403,16 +403,20 @@ function theme_webform_display_number($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_number($component, $sids = array(), $single = FALSE) {
+function _webform_analysis_number($component, $sids = array(), $single = FALSE, $join = NULL) {
   $advanced_stats = $single;
 
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
     ->fields('wsd', array('data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid']);
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid']);
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $population = array();
diff --git a/components/select.inc b/components/select.inc
index 4e1492e..aa8d68b 100644
--- a/components/select.inc
+++ b/components/select.inc
@@ -623,16 +623,21 @@ function theme_webform_display_select($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_select($component, $sids = array(), $single = FALSE) {
+function _webform_analysis_select($component, $sids = array(), $single = FALSE, $join = NULL) {
   $options = _webform_select_options($component, TRUE);
 
   // Create a generic query for the component.
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid'])
-    ->condition('data', '', '<>');
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid'])
+    ->condition('wsd.data', '', '<>');
+
   if ($sids) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   // Clone the query for later use, if needed.
@@ -649,11 +654,11 @@ function _webform_analysis_select($component, $sids = array(), $single = FALSE)
 
   if ($options) {
     // Gather the normal results first (not "other" options).
-    $query->addExpression('COUNT(data)', 'datacount');
+    $query->addExpression('COUNT(wsd.data)', 'datacount');
     $result = $query
-      ->condition('data', array_keys($options), 'IN')
+      ->condition('wsd.data', array_keys($options), 'IN')
       ->fields('wsd', array('data'))
-      ->groupBy('data')
+      ->groupBy('wsd.data')
       ->execute();
     foreach ($result as $data) {
       $display_option = isset($options[$data['data']]) ? $options[$data['data']] : $data['data'];
@@ -681,12 +686,12 @@ function _webform_analysis_select($component, $sids = array(), $single = FALSE)
 
     // If showing all results, execute the "other" query and append their rows.
     if ($single) {
-      $other_query->addExpression('COUNT(data)', 'datacount');
+      $other_query->addExpression('COUNT(wsd.data)', 'datacount');
       $other_query
         ->fields('wsd', array('data'))
-        ->groupBy('data');
+        ->groupBy('wsd.data');
       if ($options) {
-        $other_query->condition('data', array_keys($options), 'NOT IN');
+        $other_query->condition('wsd.data', array_keys($options), 'NOT IN');
       }
       $other_result = $other_query->execute();
       foreach ($other_result as $data) {
diff --git a/components/textarea.inc b/components/textarea.inc
index 1e7e301..545b597 100644
--- a/components/textarea.inc
+++ b/components/textarea.inc
@@ -176,14 +176,18 @@ function theme_webform_display_textarea($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_textarea($component, $sids = array()) {
+function _webform_analysis_textarea($component, $sids = array(), $single = FALSE, $join = NULL) {
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
     ->fields('wsd', array('no', 'data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid']);
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid']);
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $nonblanks = 0;
diff --git a/components/textfield.inc b/components/textfield.inc
index e7cb104..6d6f12d 100644
--- a/components/textfield.inc
+++ b/components/textfield.inc
@@ -214,14 +214,18 @@ function theme_webform_display_textfield($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_textfield($component, $sids = array()) {
+function _webform_analysis_textfield($component, $sids = array(), $single = FALSE, $join = NULL) {
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
     ->fields('wsd', array('data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid']);
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid']);
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $nonblanks = 0;
diff --git a/components/time.inc b/components/time.inc
index 6dcda65..7a6f896 100644
--- a/components/time.inc
+++ b/components/time.inc
@@ -327,15 +327,19 @@ function theme_webform_display_time($variables) {
 /**
  * Implements _webform_analysis_component().
  */
-function _webform_analysis_time($component, $sids = array()) {
+function _webform_analysis_time($component, $sids = array(), $single = FALSE, $join = NULL) {
   $query = db_select('webform_submitted_data', 'wsd', array('fetch' => PDO::FETCH_ASSOC))
     ->fields('wsd', array('no', 'data'))
-    ->condition('nid', $component['nid'])
-    ->condition('cid', $component['cid'])
-    ->orderBy('sid');
+    ->condition('wsd.nid', $component['nid'])
+    ->condition('wsd.cid', $component['cid'])
+    ->orderBy('wsd.sid');
 
   if (count($sids)) {
-    $query->condition('sid', $sids, 'IN');
+    $query->condition('wsd.sid', $sids, 'IN');
+  }
+
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
   }
 
   $result = $query->execute();
diff --git a/includes/webform.report.inc b/includes/webform.report.inc
index dc6ddbd..a3fb9e1 100644
--- a/includes/webform.report.inc
+++ b/includes/webform.report.inc
@@ -1412,6 +1412,34 @@ function webform_results_analysis($node, $sids = array(), $analysis_component =
     '#component' => $analysis_component,
   );
 
+  // See if a query (possibly with exposed filter) needs to restrict the
+  // submissions that are being analyzed.
+  $query = NULL;
+  if (empty($sids)) {
+    $view = webform_get_view($node, 'webform_analysis');
+    if ($view->type != t('Default') || $view->name != 'webform_analysis') {
+      // The view has been customized from the no-op built-in view. Use it.
+      $view->set_display();
+      $view->init_handlers();
+      $view->override_url = $_GET['q'];
+      $view->preview = TRUE;
+      $view->pre_execute(array($node->nid));
+      $view->build();
+      // Let modules modify the view just prior to executing it.
+      foreach (module_implements('views_pre_execute') as $module) {
+        $function = $module . '_views_pre_execute';
+        $function($view);
+      }
+      // If the view is already executed, there was an error in generating it.
+      $query = $view->executed ? NULL : $view->query->query();
+      $view->post_execute();
+  
+      if (isset($view->exposed_widgets)) {
+        $analysis['exposed_filter']['#markup'] = $view->exposed_widgets;
+      }
+    }
+  }
+
   // If showing all components, display selection form.
   if (!$analysis_component) {
     $analysis['form'] = drupal_get_form('webform_analysis_components_form', $node);
@@ -1422,7 +1450,7 @@ function webform_results_analysis($node, $sids = array(), $analysis_component =
   foreach ($components as $cid) {
     // Do component specific call.
     $component = $node->webform['components'][$cid];
-    if ($data = webform_component_invoke($component['type'], 'analysis', $component, $sids, isset($analysis_component))) {
+    if ($data = webform_component_invoke($component['type'], 'analysis', $component, $sids, isset($analysis_component), $query)) {
       drupal_alter('webform_analysis_component_data', $data, $node, $component);
       $analysis['data'][$cid] = array(
         '#theme' => array('webform_analysis_component__' . $node->nid . '__' . $cid, 'webform_analysis_component__' . $node->nid, 'webform_analysis_component'),
diff --git a/templates/webform-analysis.tpl.php b/templates/webform-analysis.tpl.php
index 734fab8..2525a93 100644
--- a/templates/webform-analysis.tpl.php
+++ b/templates/webform-analysis.tpl.php
@@ -9,6 +9,9 @@
  *   contain a Webform component. Otherwise all components are having their
  *   analysis printed on the same page.
  * - $analysis: A renderable object containing the following children:
+ *   - 'exposed_filter': The output of any exposed filter created by the
+ *     webform_analysis, webform_analysis_CONTENTTYPE, or webform_analysis_NID
+ *     view.
  *   - 'form': A form for selecting which components should be included in the
  *     analysis.
  *   - 'data': An render array of analysis results for each component enabled.
@@ -17,6 +20,7 @@
 <div class="webform-analysis">
   <?php print drupal_render($analysis['form']['help']); ?>
 
+  <?php print drupal_render($analysis['exposed_filter']); ?>
   <div class="webform-analysis-data">
     <?php print drupal_render($analysis['data']); ?>
   </div>
diff --git a/views/default_views/webform_analysis.inc b/views/default_views/webform_analysis.inc
new file mode 100644
index 0000000..24acc08
--- /dev/null
+++ b/views/default_views/webform_analysis.inc
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * webform_analysis view definition.
+ */
+
+// --- Paste exported view below ---
+
+$view = new view();
+$view->name = 'webform_analysis';
+$view->description = 'Limit submissions for the webform node\'s analysis. Query must have sid as a field. Don\'t duplicate sids in result.';
+$view->tag = 'webform';
+$view->base_table = 'webform_submissions';
+$view->human_name = 'Webform Analysis';
+$view->core = 7;
+$view->api_version = '3.0';
+$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+
+/* Display: Master */
+$handler = $view->new_display('default', 'Master', 'default');
+$handler->display->display_options['use_more_always'] = FALSE;
+$handler->display->display_options['access']['type'] = 'none';
+$handler->display->display_options['cache']['type'] = 'none';
+$handler->display->display_options['query']['type'] = 'views_query';
+$handler->display->display_options['query']['options']['distinct'] = TRUE;
+$handler->display->display_options['exposed_form']['type'] = 'basic';
+$handler->display->display_options['pager']['type'] = 'none';
+$handler->display->display_options['pager']['options']['offset'] = '0';
+$handler->display->display_options['style_plugin'] = 'default';
+$handler->display->display_options['row_plugin'] = 'fields';
+/* Field: Webform submissions: Sid */
+$handler->display->display_options['fields']['sid']['id'] = 'sid';
+$handler->display->display_options['fields']['sid']['table'] = 'webform_submissions';
+$handler->display->display_options['fields']['sid']['field'] = 'sid';
+/* Contextual filter: Webform submissions: Node */
+$handler->display->display_options['arguments']['nid']['id'] = 'nid';
+$handler->display->display_options['arguments']['nid']['table'] = 'webform_submissions';
+$handler->display->display_options['arguments']['nid']['field'] = 'nid';
+$handler->display->display_options['arguments']['nid']['default_action'] = 'empty';
+$handler->display->display_options['arguments']['nid']['default_argument_type'] = 'fixed';
+$handler->display->display_options['arguments']['nid']['summary']['number_of_records'] = '0';
+$handler->display->display_options['arguments']['nid']['summary']['format'] = 'default_summary';
+$handler->display->display_options['arguments']['nid']['summary_options']['items_per_page'] = '25';
+$translatables['webform_analysis'] = array(
+  t('Master'),
+  t('more'),
+  t('Apply'),
+  t('Reset'),
+  t('Sort by'),
+  t('Asc'),
+  t('Desc'),
+  t('Sid'),
+  t('.'),
+  t(','),
+  t('All'),
+);
+
+// --- Paste exported view above ---
+
+$views[$view->name] = $view;
diff --git a/webform.api.php b/webform.api.php
index 4390bbb..56e6509 100644
--- a/webform.api.php
+++ b/webform.api.php
@@ -1090,6 +1090,9 @@ function _webform_theme_component() {
  *   Boolean flag determining if the details about a single component are being
  *   shown. May be used to provided detailed information about a single
  *   component's analysis, such as showing "Other" options within a select list.
+ * @param $join
+ *   An optional SelectQuery object to be used to join with the submissions
+ *   table to restrict the submissions being analyzed.
  * @return
  *   An array containing one or more of the following keys:
  *   - table_rows: If this component has numeric data that can be represented in
@@ -1110,7 +1113,7 @@ function _webform_theme_component() {
  *
  * @see _webform_defaults_component()
  */
-function _webform_analysis_component($component, $sids = array(), $single = FALSE) {
+function _webform_analysis_component($component, $sids = array(), $single = FALSE, $join = NULL) {
   // Generate the list of options and questions.
   $options = _webform_select_options_from_text($component['extra']['options'], TRUE);
   $questions = _webform_select_options_from_text($component['extra']['questions'], TRUE);
@@ -1129,6 +1132,10 @@ function _webform_analysis_component($component, $sids = array(), $single = FALS
     $query->condition('sid', $sids, 'IN');
   }
 
+  if ($join) {
+    $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
+  }
+
   $result = $query->execute();
   $counts = array();
   foreach ($result as $data) {
-- 
1.7.8.msysgit.0

