diff --git a/views/webform.views.inc b/views/webform.views.inc index dab3fe3..1afe355 100644 --- a/views/webform.views.inc +++ b/views/webform.views.inc @@ -47,6 +47,21 @@ function webform_views_data() { 'help' => t('Submissions generated from Webform forms.'), ); + $data['webform_submissions']['table']['join'] = array( + // Joins to webform_submitted_data directly. + 'webform_submitted_data' => array( + 'left_field' => 'sid', + 'field' => 'sid', + 'type' => 'INNER', + ), + 'webform_component' => array( + 'left_table' => 'webform_submitted_data', + 'left_field' => 'cid', + 'field' => 'cid', + 'type' => 'INNER', + ), + ); + // sid $data['webform_submissions']['sid'] = array( 'title' => t('Sid'), @@ -171,6 +186,90 @@ function webform_views_data() { ), ); + $data['webform_submitted_data']['table']['group'] = t('Webform submissions'); + $data['webform_submitted_data']['table']['join'] = array( + // Joins to webform_submissions directly. + 'webform_submissions' => array( + 'left_field' => 'sid', + 'field' => 'sid', + 'type' => 'INNER', + ), + // Joins to webform_component directly. + 'webform_component' => array( + 'left_field' => 'cid', + 'field' => 'cid', + 'type' => 'INNER', + 'extra' => 'webform_component.nid = webform_submitted_data.nid', + ), + ); + + $data['webform_component']['table']['group'] = t('Webform submissions'); + $data['webform_component']['table']['join'] = array( + // Joins to webform_component directly. + 'webform_submitted_data' => array( + 'left_field' => 'cid', + 'field' => 'cid', + 'type' => 'INNER', + 'extra' => 'webform_component.nid = webform_submissions.nid', + ), + // Joins to webform_submissions. + 'webform_submissions' => array( + 'left_table' => 'webform_submitted_data', + 'left_field' => 'cid', + 'field' => 'cid', + 'type' => 'INNER', + 'extra' => 'webform_submitted_data.nid = webform_component.nid', + ), + ); + + // Get a list of the available webform components. + $result = db_query("SELECT n.title, + n.nid, + wc.name, + wc.form_key, + wc.cid + FROM webform_component wc + INNER JOIN node n + ON wc.nid = n.nid + ORDER BY n.title, + wc.name, + wc.form_key"); + while ($component = db_fetch_object($result)) { + $component_key = $component->form_key . '_' . $component->nid . '_' . $component->cid; + $node = node_load($component->nid); + + switch ($node->webform['components'][$component->cid]['type']) { + case 'select': + $filter_handler = 'webform_handler_filter_component_many_to_one'; + break; + default: + $filter_handler = 'webform_handler_filter_component'; + break; + } + + $data['webform_component'][$component_key] = array( + 'title' => t('(Component from: @title) @name', array('@title' => $component->title, '@name' => $component->name)), + 'help' => t('Appears in webform !nid: @title', array('!nid' => $component->nid, '@title' => $component->title)), + 'field' => array( + 'handler' => 'webform_handler_field_component', + 'webform_options' => array( + 'cid' => $component->cid, + 'label' => $component->name, + 'nid' => $component->nid, + ), + ), + 'filter' => array( + 'title' => t('(Component from: @title) @name', array('@title' => $component->title, '@name' => $component->name)), + 'handler' => $filter_handler, + 'webform_options' => array( + 'cid' => $component->cid, + 'label' => $component->name, + 'nid' => $component->nid, + ), + ), + ); + } + return $data; } @@ -303,6 +402,18 @@ function webform_views_handlers() { 'parent' => 'views_handler_filter_boolean_operator', 'file' => 'webform_handler_filter_webform_status.inc', ), + 'webform_handler_field_component' => array( + 'parent' => 'views_handler_field', + 'file' => 'webform_handler_field_component.inc', + ), + 'webform_handler_filter_component' => array( + 'parent' => 'views_handler_filter_string', + 'file' => 'webform_handler_filter_component.inc', + ), + 'webform_handler_filter_component_many_to_one' => array( + 'parent' => 'views_handler_filter_many_to_one', + 'file' => 'webform_handler_filter_component_many_to_one.inc', + ), ), ); } \ No newline at end of file diff --git a/views/webform_handler_field_component.inc b/views/webform_handler_field_component.inc new file mode 100644 index 0000000..c523c9a --- /dev/null +++ b/views/webform_handler_field_component.inc @@ -0,0 +1,47 @@ +additional_fields['nid'] = array('table' => 'webform_submissions', 'field' => 'nid'); + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['label']['#default_value'] = ($this->options['label'] !== $this->definition['title']) ? $this->options['label'] : $this->definition['webform_options']['label']; + } + + function query() { + $this->add_additional_fields(); + } + + function pre_render($values) { + if (!function_exists('webform_get_submission')) { + module_load_include('inc', 'webform', 'includes/webform.submissions'); + } + $this->webform_submissions = array(); + foreach ($values as $submission) { + $this->webform_submissions[$submission->sid] = webform_get_submission($submission->webform_submissions_nid, $submission->sid); + } + } + + function render($values) { + // If this value is from a select, display the component value. + $node = node_load($this->definition['webform_options']['nid']); + switch ($node->webform['components'][$this->definition['webform_options']['cid']]['type']) { + case 'select': + $pairs = _webform_select_options($node->webform['components'][$this->definition['webform_options']['cid']]); + $returns = array(); + foreach ($this->webform_submissions[$values->sid]->data[$this->definition['webform_options']['cid']]['value'] as $key) { + $returns[] = $pairs[$key]; + } + $return = implode(', ', $returns); + break; + default: + $return = implode(', ', $this->webform_submissions[$values->sid]->data[$this->definition['webform_options']['cid']]['value']); + } + return $return; + } + +} diff --git a/views/webform_handler_filter_component.inc b/views/webform_handler_filter_component.inc new file mode 100644 index 0000000..3109b1b --- /dev/null +++ b/views/webform_handler_filter_component.inc @@ -0,0 +1,133 @@ +options['expose']['label'] !== $this->ui_name()) ? $this->options['expose']['label'] : $this->definition['webform_options']['label']; + } + + function query() { + $upper = $this->case_transform(); + $info = $this->operators(); + if (!empty($info[$this->operator]['method']) && $this->value !== '') { + // The schema of webform doesn't really allow easy access to the data. + // We query the data table separate to get valid sids, then filter on + // these sids. + $sql = "SELECT sid + FROM webform_submitted_data + WHERE cid = %d + AND nid = %d"; + $params = array($this->definition['webform_options']['cid'], $this->definition['webform_options']['nid']); + + // Build additional WHERE clause based on operator. + $sub_sql = $this->{$info[$this->operator]['method']}('webform_submitted_data.data', $upper); + + // This may bring back additional params. + if (is_array($sub_sql)) { + $params = array_merge($params, $sub_sql[1]); + $sub_sql = $sub_sql[0]; + } + else { + $params[] = $this->value; + } + + // Create SQL. + if (!empty($sub_sql)) { + $sql .= ' AND ' . $sub_sql; + } + + $result = db_query($sql, $params); + + $sids = array(); + while ($items = db_fetch_object($result)) { + $sids[] = $items->sid; + } + + if (!empty($sids)) { + $this->query->add_where($this->options['group'], "webform_submissions.sid IN (" . db_placeholders($sids) . ")", $sids); + } + else { + // Prevent query from happening. @todo Is there a better way to do this? + $this->query->add_where($this->options['group'], "0"); + } + } + } + + function op_equal($field, $upper) { + // operator is either = or != + return "$upper($field) $this->operator $upper('%s')"; + } + + function op_contains($field, $upper) { + return "$upper($field) LIKE $upper('%%%s%%')"; + } + + function op_word($field, $upper) { + $where = array(); + preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' ' . $this->value, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $phrase = false; + // Strip off phrase quotes + if ($match[2]{0} == '"') { + $match[2] = substr($match[2], 1, -1); + $phrase = true; + } + $words = trim($match[2], ',?!();:-'); + $words = $phrase ? array($words) : preg_split('/ /', $words, -1, PREG_SPLIT_NO_EMPTY); + foreach ($words as $word) { + $where[] = "$upper($field) LIKE $upper('%%%s%%')"; + $values[] = trim($word, " ,!?"); + } + } + + if (!$where) { + return; + } + + if ($this->operator == 'word') { + $where = '(' . implode(' OR ', $where) . ')'; + } + else { + $where = implode(' AND ', $where); + } + return array($where, $values); + } + + function op_starts($field, $upper) { + return "$upper($field) LIKE $upper('%s%%')"; + } + + function op_not_starts($field, $upper) { + return "$upper($field) NOT LIKE $upper('%s%%')"; + } + + function op_ends($field, $upper) { + return "$upper($field) LIKE $upper('%%%s')"; + } + + function op_not_ends($field, $upper) { + return "$upper($field) NOT LIKE $upper('%%%s')"; + } + + function op_not($field, $upper) { + return "$upper($field) NOT LIKE $upper('%%%s%%')"; + } + + function op_empty($field) { + if ($this->operator == 'empty') { + $operator = "IS NULL"; + } + else { + $operator = "IS NOT NULL"; + } + + return "$field $operator"; + } + +} diff --git a/views/webform_handler_filter_component_many_to_one.inc b/views/webform_handler_filter_component_many_to_one.inc new file mode 100644 index 0000000..9acc88e --- /dev/null +++ b/views/webform_handler_filter_component_many_to_one.inc @@ -0,0 +1,143 @@ +content_field = content_fields($this->definition['content_field_name']); + // $this->additional_fields = $this->definition['additional fields']; + // $field = $this->content_field; + // $this->value_title = $field['widget']['label']; + // } + + function expose_form_left(&$form, &$form_state) { + parent::expose_form_left($form, $form_state); + $form['expose']['label']['#default_value'] = ($this->options['expose']['label'] !== $this->ui_name()) ? $this->options['expose']['label'] : $this->definition['webform_options']['label']; + } + + function get_value_options() { + $this->value_options = $this->allowed_values(); + } + + // Get allowed values from hook_allowed_values(), if any, + // or from content_allowed_values(); + function allowed_values() { + $node = node_load($this->definition['webform_options']['nid']); + return _webform_select_options($node->webform['components'][$this->definition['webform_options']['cid']]); + } + + + function query() { + + $info = $this->operators(); + if (!empty($info[$this->operator]['method']) && $this->value !== '') { + // The schema of webform doesn't really allow easy access to the data. + // We query the data table separate to get valid sids, then filter on + // these sids. + $sql = "SELECT sid + FROM webform_submitted_data + WHERE cid = %d + AND nid = %d"; + $params = array($this->definition['webform_options']['cid'], $this->definition['webform_options']['nid']); + + // Build additional WHERE clause based on operator. + $sub_sql = $this->{$info[$this->operator]['method']}(); + + // This may bring back additional params. + if (is_array($sub_sql)) { + $params = array_merge($params, $sub_sql[1]); + $sub_sql = $sub_sql[0]; + } + else { + $params = array_merge($params, $this->value); + } + + // Create SQL. + if (!empty($sub_sql)) { + $sql .= ' AND ' . $sub_sql; + } + + $result = db_query($sql, $params); + + $sids = array(); + while ($items = db_fetch_object($result)) { + $sids[] = $items->sid; + } + + if (!empty($sids)) { + $this->query->add_where($this->options['group'], "webform_submissions.sid IN (" . db_placeholders($sids) . ")", $sids); + } + else { + // Prevent query from happening. @todo Is there a better way to do this? + $this->query->add_where($this->options['group'], "0"); + } + } + } + + function op_simple() { + if (empty($this->value)) { + return; + } + + $placeholder = !empty($this->definition['numeric']) ? '%d' : "'%s'"; + + $replace = array_fill(0, sizeof($this->value), $placeholder); + $in = ' (' . implode(", ", $replace) . ')'; + + // We use array_values() because the checkboxes keep keys and that can cause + // array addition problems. + return array("webform_submitted_data.data " . $this->operator . $in, array_values($this->value)); + } + + function op_empty() { + + if ($this->operator == 'empty') { + $operator = "IS NULL"; + } + else { + $operator = "IS NOT NULL"; + } + + return "webform_submitted_data.data $operator"; + } + + function op_helper() { + + $field = 'webform_submitted_data.data'; + $options = $this->options; + $operator = $this->operator; + if (empty($options['group'])) { + $options['group'] = 0; + } + + if ($operator == 'not') { + $return = "$field IS NULL"; + } + else if ($operator == 'or' && empty($options['reduce_duplicates'])) { + if (count($this->value) > 1) { + $returns = array(); + for ($i=0; $i < count($this->value); $i++) { + $returns[] = "$field LIKE '%%%s%%'"; + } + $return = implode(' AND ', $returns); + } + else { + $return = "$field LIKE '%%%s%%'"; + } + } + else { + $clauses = array(); + foreach ($this->table_aliases as $value => $alias) { + $clauses[] = "$field LIKE '%%%s%%'"; + } + + // implode on either AND or OR. + $return = implode(' ' . strtoupper($operator) . ' ', $clauses); + } + return $return; + } + +}