Drupal 7 WebForm is a kind of a double edge sword just like any other Drupal contribution modules.
It creates a beautiful and fully functional web forms but makes customizing work a hard task. Of course it provides hooks but even those functions are not clearly defined some reasonings and other times it doesn’t provide things we need. I think the lack of support has a lot to do with the data structure of the WebForm; we already know it isn’t created by the best mind of structuring. I wouldn’t say this is a flaw but it is definitely not an advantage. Maybe that’s why there are some Drupal folks try to avoid WebForm. Maybe those flaws will go away when Drupal 8 rolls out; well, that’s beside of the point.
I used a WebForm because of the simplicity. Then later I faced a need bringing the data according to a predefined range. As you know, WebForm stores data vertically and bringing a record in horizontally isn’t a hard task if you’re familiar with SQL; however adding a range can be a challenge. Well, not quite if you understand WebForm is a content type. It means it is a node from Drupal point of view.
Here is an example:
/**
* Queries and returns WebForm data with range
* @param int $nid Webform Node Id
* @param int $cid Webform field Id, the order of the webform field you created in webform_component table)
* @return $result Returns WebForm data object or null if not found
*/
function get_results_with_range($nid, $cid) {
// sub_data field collects other field information
// so that group by sid is necessary
// NOTE: sid is Serial Id of data
$sql = "SELECT sd.sid, group_concat(IFNULL(sd.data, '') SEPARATOR ';') AS sub_data, rd.d_range, rd.d_order
FROM {webform_submitted_data} AS sd
JOIN (
SELECT sid, data,
CASE
WHEN data >= 91 THEN 'Over 90'
WHEN data >= 80 AND data <= 90 THEN '81 - 90'
WHEN data >= 70 AND data <= 80 THEN '71 - 80'
WHEN data >= 60 AND data <= 70 THEN '61 - 60'
ELSE 'Under 60'
END AS d_range,
CASE
WHEN data >= 91 THEN 1
WHEN data >= 80 AND data <= 90 THEN 2
WHEN data >= 70 AND data <= 80 THEN 3
WHEN data >= 60 AND data <= 70 THEN 4
ELSE 5
END AS d_order
FROM {webform_submitted_data}
WHERE nid = :nid AND cid = :cid
AND data != ''
) AS rd
ON sd.sid = rd.sid
WHERE sd.nid = :nid
GROUP BY sd.sid
ORDER BY rd.d_order;";
return db_query($sql, array(':nid' => $nid, ':cid' => $cid));
}
Displaying the results is pretty much intuitive. Here is an example:
/**
* Getting html from WebForm data with range
* @param object $result SQL results set
* @return $html Returns html with a set of list
*/
function html_range_results($results) {
$html = '';
if ($results) {
$old_range = '';
$html .= '<ul>';
foreach ($results as $row) {
$sub_data = $row->sub_data;
$new_range = $row->d_range;
if (!empty($sub_data)) {
// if range is different from the previous one
if ($old_range != $new_range) {
// taking care of html combination
$html .= (empty($old_range) ? '' : '</ul>');
// add a new range header
$html .= '<h3>' . $new_range . '</h3>';
$html .= '<ul>';
}
$data_array = explode(';', $sub_data);
// let's say first field holds user name and we need to display it
$user_name = $data_array[0];
$html .= '<li>' . $user_name . '</li>';
}
$old_range = $new_range;
}
$html .= '</ul>';
}
return $html;
}