1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* @file
|
5
|
* Webform module grid component.
|
6
|
*/
|
7
|
|
8
|
// Grid depends on functions provided by select.
|
9
|
webform_component_include('select');
|
10
|
|
11
|
/**
|
12
|
* Implements _webform_defaults_component().
|
13
|
*/
|
14
|
function _webform_defaults_grid() {
|
15
|
return array(
|
16
|
'name' => '',
|
17
|
'form_key' => NULL,
|
18
|
'mandatory' => 0,
|
19
|
'pid' => 0,
|
20
|
'weight' => 0,
|
21
|
'extra' => array(
|
22
|
'options' => '',
|
23
|
'questions' => '',
|
24
|
'optrand' => 0,
|
25
|
'qrand' => 0,
|
26
|
'title_display' => 0,
|
27
|
'custom_option_keys' => 0,
|
28
|
'custom_question_keys' => 0,
|
29
|
'description' => '',
|
30
|
'private' => FALSE,
|
31
|
),
|
32
|
);
|
33
|
}
|
34
|
|
35
|
|
36
|
/**
|
37
|
* Implements _webform_theme_component().
|
38
|
*/
|
39
|
function _webform_theme_grid() {
|
40
|
return array(
|
41
|
'webform_grid' => array(
|
42
|
'render element' => 'element',
|
43
|
'file' => 'components/grid.inc',
|
44
|
),
|
45
|
'webform_display_grid' => array(
|
46
|
'render element' => 'element',
|
47
|
'file' => 'components/grid.inc',
|
48
|
),
|
49
|
);
|
50
|
}
|
51
|
|
52
|
/**
|
53
|
* Implements _webform_edit_component().
|
54
|
*/
|
55
|
function _webform_edit_grid($component) {
|
56
|
$form = array();
|
57
|
|
58
|
if (module_exists('options_element')) {
|
59
|
$form['options'] = array(
|
60
|
'#type' => 'fieldset',
|
61
|
'#title' => t('Options'),
|
62
|
'#collapsible' => TRUE,
|
63
|
'#description' => t('Options to select across the top. Usually these are ratings such as "poor" through "excellent" or "strongly disagree" through "strongly agree".'),
|
64
|
'#attributes' => array('class' => array('webform-options-element')),
|
65
|
'#element_validate' => array('_webform_edit_validate_options'),
|
66
|
);
|
67
|
$form['options']['options'] = array(
|
68
|
'#type' => 'options',
|
69
|
'#options' => _webform_select_options_from_text($component['extra']['options'], TRUE),
|
70
|
'#optgroups' => FALSE,
|
71
|
'#default_value' => FALSE,
|
72
|
'#default_value_allowed' => FALSE,
|
73
|
'#optgroups' => FALSE,
|
74
|
'#key_type' => 'mixed',
|
75
|
'#key_type_toggle' => t('Customize option keys (Advanced)'),
|
76
|
'#key_type_toggled' => $component['extra']['custom_option_keys'],
|
77
|
);
|
78
|
|
79
|
$form['questions'] = array(
|
80
|
'#type' => 'fieldset',
|
81
|
'#title' => t('Questions'),
|
82
|
'#collapsible' => TRUE,
|
83
|
'#description' => t('Questions list down the side of the grid.'),
|
84
|
'#attributes' => array('class' => array('webform-options-element')),
|
85
|
'#element_validate' => array('_webform_edit_validate_options'),
|
86
|
);
|
87
|
$form['questions']['options'] = array(
|
88
|
'#type' => 'options',
|
89
|
'#options' => _webform_select_options_from_text($component['extra']['questions'], TRUE),
|
90
|
'#optgroups' => FALSE,
|
91
|
'#default_value' => FALSE,
|
92
|
'#default_value_allowed' => FALSE,
|
93
|
'#optgroups' => FALSE,
|
94
|
'#key_type' => 'mixed',
|
95
|
'#key_type_toggle' => t('Customize question keys (Advanced)'),
|
96
|
'#key_type_toggled' => $component['extra']['custom_question_keys'],
|
97
|
);
|
98
|
}
|
99
|
else {
|
100
|
$form['extra']['options'] = array(
|
101
|
'#type' => 'textarea',
|
102
|
'#title' => t('Options'),
|
103
|
'#default_value' => $component['extra']['options'],
|
104
|
'#description' => t('Options to select across the top. One option per line. <strong>Key-value pairs MUST be specified as "safe_key|Some readable option"</strong>. Use of only alphanumeric characters and underscores is recommended in keys.') . theme('webform_token_help'),
|
105
|
'#cols' => 60,
|
106
|
'#rows' => 5,
|
107
|
'#weight' => -3,
|
108
|
'#required' => TRUE,
|
109
|
'#wysiwyg' => FALSE,
|
110
|
'#element_validate' => array('_webform_edit_validate_select'),
|
111
|
);
|
112
|
$form['extra']['questions'] = array(
|
113
|
'#type' => 'textarea',
|
114
|
'#title' => t('Questions'),
|
115
|
'#default_value' => $component['extra']['questions'],
|
116
|
'#description' => t('Questions list down the side of the grid. One question per line. <strong>Key-value pairs MUST be specified as "safe_key|Some readable option"</strong>. Use of only alphanumeric characters and underscores is recommended in keys.') . theme('webform_token_help'),
|
117
|
'#cols' => 60,
|
118
|
'#rows' => 5,
|
119
|
'#weight' => -2,
|
120
|
'#required' => TRUE,
|
121
|
'#wysiwyg' => FALSE,
|
122
|
'#element_validate' => array('_webform_edit_validate_select'),
|
123
|
);
|
124
|
}
|
125
|
|
126
|
$form['display']['optrand'] = array(
|
127
|
'#type' => 'checkbox',
|
128
|
'#title' => t('Randomize Options'),
|
129
|
'#default_value' => $component['extra']['optrand'],
|
130
|
'#description' => t('Randomizes the order of options on the top when they are displayed in the form.'),
|
131
|
'#parents' => array('extra', 'optrand')
|
132
|
);
|
133
|
$form['display']['qrand'] = array(
|
134
|
'#type' => 'checkbox',
|
135
|
'#title' => t('Randomize Questions'),
|
136
|
'#default_value' => $component['extra']['qrand'],
|
137
|
'#description' => t('Randomize the order of the questions on the side when they are displayed in the form.'),
|
138
|
'#parents' => array('extra', 'qrand')
|
139
|
);
|
140
|
return $form;
|
141
|
}
|
142
|
|
143
|
/**
|
144
|
* Implements _webform_render_component().
|
145
|
*/
|
146
|
function _webform_render_grid($component, $value = NULL, $filter = TRUE) {
|
147
|
$node = isset($component['nid']) ? node_load($component['nid']) : NULL;
|
148
|
|
149
|
$element = array(
|
150
|
'#type' => 'webform_grid',
|
151
|
'#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
|
152
|
'#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
|
153
|
'#required' => $component['mandatory'],
|
154
|
'#weight' => $component['weight'],
|
155
|
'#description' => $filter ? _webform_filter_descriptions($component['extra']['description'], $node) : $component['extra']['description'],
|
156
|
'#grid_questions' => _webform_select_options_from_text($component['extra']['questions'], TRUE),
|
157
|
'#grid_options' => _webform_select_options_from_text($component['extra']['options'], TRUE),
|
158
|
'#optrand' => $component['extra']['optrand'],
|
159
|
'#qrand' => $component['extra']['qrand'],
|
160
|
'#theme' => 'webform_grid',
|
161
|
'#theme_wrappers' => array('webform_element'),
|
162
|
'#process' => array('webform_expand_grid'),
|
163
|
'#translatable' => array('title', 'description', 'grid_options', 'grid_questions'),
|
164
|
);
|
165
|
|
166
|
if ($value) {
|
167
|
$element['#default_value'] = $value;
|
168
|
}
|
169
|
|
170
|
return $element;
|
171
|
}
|
172
|
|
173
|
/**
|
174
|
* A Form API #process function for Webform grid fields.
|
175
|
*/
|
176
|
function webform_expand_grid($element) {
|
177
|
$options = $element['#grid_options'];
|
178
|
$questions = $element['#grid_questions'];
|
179
|
|
180
|
if (!empty($element['#optrand'])) {
|
181
|
_webform_shuffle_options($options);
|
182
|
}
|
183
|
|
184
|
if (!empty($element['#qrand'])) {
|
185
|
_webform_shuffle_options($questions);
|
186
|
}
|
187
|
|
188
|
foreach ($questions as $key => $question) {
|
189
|
if ($question != '') {
|
190
|
$element[$key] = array(
|
191
|
'#title' => $question,
|
192
|
'#required' => $element['#required'],
|
193
|
'#options' => $options,
|
194
|
'#type' => 'radios',
|
195
|
'#process' => array('form_process_radios', 'webform_expand_select_ids'),
|
196
|
|
197
|
// Webform handles validation manually.
|
198
|
'#validated' => TRUE,
|
199
|
'#webform_validated' => FALSE,
|
200
|
'#translatable' => array('title'),
|
201
|
);
|
202
|
}
|
203
|
}
|
204
|
|
205
|
$value = isset($element['#default_value']) ? $element['#default_value'] : array();
|
206
|
foreach (element_children($element) as $key) {
|
207
|
if (isset($value[$key])) {
|
208
|
$element[$key]['#default_value'] = ($value[$key] !== '') ? $value[$key] : NULL;
|
209
|
}
|
210
|
else {
|
211
|
$element[$key]['#default_value'] = NULL;
|
212
|
}
|
213
|
}
|
214
|
|
215
|
return $element;
|
216
|
}
|
217
|
|
218
|
/**
|
219
|
* Implements _webform_display_component().
|
220
|
*/
|
221
|
function _webform_display_grid($component, $value, $format = 'html') {
|
222
|
$questions = _webform_select_options_from_text($component['extra']['questions'], TRUE);
|
223
|
$options = _webform_select_options_from_text($component['extra']['options'], TRUE);
|
224
|
|
225
|
$element = array(
|
226
|
'#title' => $component['name'],
|
227
|
'#weight' => $component['weight'],
|
228
|
'#format' => $format,
|
229
|
'#grid_questions' => $questions,
|
230
|
'#grid_options' => $options,
|
231
|
'#theme' => 'webform_display_grid',
|
232
|
'#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'),
|
233
|
'#sorted' => TRUE,
|
234
|
'#translatable' => array('#title', '#grid_questions', '#grid_options'),
|
235
|
);
|
236
|
|
237
|
foreach ($questions as $key => $question) {
|
238
|
if ($question !== '') {
|
239
|
$element[$key] = array(
|
240
|
'#title' => $question,
|
241
|
'#value' => isset($value[$key]) ? $value[$key] : NULL,
|
242
|
'#translatable' => array('#title', '#value'),
|
243
|
);
|
244
|
}
|
245
|
}
|
246
|
|
247
|
return $element;
|
248
|
}
|
249
|
|
250
|
/**
|
251
|
* Format the text output for this component.
|
252
|
*/
|
253
|
function theme_webform_display_grid($variables) {
|
254
|
$element = $variables['element'];
|
255
|
|
256
|
$component = $element['#webform_component'];
|
257
|
$format = $element['#format'];
|
258
|
|
259
|
if ($format == 'html') {
|
260
|
$rows = array();
|
261
|
$header = array(array('data' => '', 'class' => array('webform-grid-question')));
|
262
|
foreach ($element['#grid_options'] as $option) {
|
263
|
$header[] = array('data' => _webform_filter_xss($option), 'class' => array('checkbox', 'webform-grid-option'));
|
264
|
}
|
265
|
foreach ($element['#grid_questions'] as $question_key => $question) {
|
266
|
$row = array();
|
267
|
$row[] = array('data' => _webform_filter_xss($question), 'class' => array('webform-grid-question'));
|
268
|
foreach ($element['#grid_options'] as $option_value => $option_label) {
|
269
|
if (strcmp($element[$question_key]['#value'], $option_value) == 0) {
|
270
|
$row[] = array('data' => '<strong>X</strong>', 'class' => array('checkbox', 'webform-grid-option'));
|
271
|
}
|
272
|
else {
|
273
|
$row[] = array('data' => ' ', 'class' => array('checkbox', 'webform-grid-option'));
|
274
|
}
|
275
|
}
|
276
|
$rows[] = $row;
|
277
|
}
|
278
|
|
279
|
$option_count = count($header) - 1;
|
280
|
$output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('class' => array('webform-grid', 'webform-grid-' . $option_count))));
|
281
|
}
|
282
|
else {
|
283
|
$items = array();
|
284
|
foreach (element_children($element) as $key) {
|
285
|
$items[] = ' - ' . $element[$key]['#title'] . ': ' . (isset($element['#grid_options'][$element[$key]['#value']]) ? $element['#grid_options'][$element[$key]['#value']] : '');
|
286
|
}
|
287
|
$output = implode("\n", $items);
|
288
|
}
|
289
|
|
290
|
return $output;
|
291
|
}
|
292
|
|
293
|
/**
|
294
|
* Implements _webform_analysis_component().
|
295
|
*/
|
296
|
function _webform_analysis_grid($component, $sids = array()) {
|
297
|
// Generate the list of options and questions.
|
298
|
$options = _webform_select_options_from_text($component['extra']['options'], TRUE);
|
299
|
$questions = _webform_select_options_from_text($component['extra']['questions'], TRUE);
|
300
|
|
301
|
// Generate a lookup table of results.
|
302
|
$query = db_select('webform_submitted_data', 'wsd')
|
303
|
->fields('wsd', array('no', 'data'))
|
304
|
->condition('nid', $component['nid'])
|
305
|
->condition('cid', $component['cid'])
|
306
|
->condition('data', '', '<>')
|
307
|
->groupBy('no')
|
308
|
->groupBy('data');
|
309
|
$query->addExpression('COUNT(sid)', 'datacount');
|
310
|
|
311
|
if (count($sids)) {
|
312
|
$query->condition('sid', $sids, 'IN');
|
313
|
}
|
314
|
|
315
|
$result = $query->execute();
|
316
|
$counts = array();
|
317
|
foreach ($result as $data) {
|
318
|
$counts[$data->no][$data->data] = $data->datacount;
|
319
|
}
|
320
|
|
321
|
// Create an entire table to be put into the returned row.
|
322
|
$rows = array();
|
323
|
$header = array('');
|
324
|
|
325
|
// Add options as a header row.
|
326
|
foreach ($options as $option) {
|
327
|
$header[] = _webform_filter_xss($option);
|
328
|
}
|
329
|
|
330
|
// Add questions as each row.
|
331
|
foreach ($questions as $qkey => $question) {
|
332
|
$row = array(_webform_filter_xss($question));
|
333
|
foreach ($options as $okey => $option) {
|
334
|
$row[] = !empty($counts[$qkey][$okey]) ? $counts[$qkey][$okey] : 0;
|
335
|
}
|
336
|
$rows[] = $row;
|
337
|
}
|
338
|
$output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('class' => array('webform-grid'))));
|
339
|
|
340
|
|
341
|
return array(array(array('data' => $output, 'colspan' => 2)));
|
342
|
}
|
343
|
|
344
|
/**
|
345
|
* Implements _webform_table_component().
|
346
|
*/
|
347
|
function _webform_table_grid($component, $value) {
|
348
|
$questions = _webform_select_options_from_text($component['extra']['questions'], TRUE);
|
349
|
$options = _webform_select_options_from_text($component['extra']['options'], TRUE);
|
350
|
|
351
|
$output = '';
|
352
|
// Set the value as a single string.
|
353
|
foreach ($questions as $key => $label) {
|
354
|
if (isset($value[$key]) && isset($options[$value[$key]])) {
|
355
|
$output .= _webform_filter_xss($label) . ': ' . _webform_filter_xss($options[$value[$key]]) . '<br />';
|
356
|
}
|
357
|
}
|
358
|
|
359
|
return $output;
|
360
|
}
|
361
|
|
362
|
/**
|
363
|
* Implements _webform_csv_headers_component().
|
364
|
*/
|
365
|
function _webform_csv_headers_grid($component, $export_options) {
|
366
|
$header = array();
|
367
|
$header[0] = array('');
|
368
|
$header[1] = array($component['name']);
|
369
|
$items = _webform_select_options_from_text($component['extra']['questions'], TRUE);
|
370
|
$count = 0;
|
371
|
foreach ($items as $key => $item) {
|
372
|
// Empty column per sub-field in main header.
|
373
|
if ($count != 0) {
|
374
|
$header[0][] = '';
|
375
|
$header[1][] = '';
|
376
|
}
|
377
|
// The value for this option.
|
378
|
$header[2][] = $item;
|
379
|
$count++;
|
380
|
}
|
381
|
|
382
|
return $header;
|
383
|
}
|
384
|
|
385
|
/**
|
386
|
* Implements _webform_csv_data_component().
|
387
|
*/
|
388
|
function _webform_csv_data_grid($component, $export_options, $value) {
|
389
|
$questions = _webform_select_options_from_text($component['extra']['questions'], TRUE);
|
390
|
$options = _webform_select_options_from_text($component['extra']['options'], TRUE);
|
391
|
$return = array();
|
392
|
foreach ($questions as $key => $question) {
|
393
|
if (isset($value[$key]) && isset($options[$value[$key]])) {
|
394
|
$return[] = $export_options['select_keys'] ? $value[$key] : $options[$value[$key]];
|
395
|
}
|
396
|
else {
|
397
|
$return[] = '';
|
398
|
}
|
399
|
}
|
400
|
return $return;
|
401
|
}
|
402
|
|
403
|
function theme_webform_grid($variables) {
|
404
|
$element = $variables['element'];
|
405
|
|
406
|
$rows = array();
|
407
|
$header = array(array('data' => '', 'class' => array('webform-grid-question')));
|
408
|
// Set the header for the table.
|
409
|
foreach ($element['#grid_options'] as $option) {
|
410
|
$header[] = array('data' => _webform_filter_xss($option), 'class' => array('checkbox', 'webform-grid-option'));
|
411
|
}
|
412
|
|
413
|
foreach (element_children($element) as $key) {
|
414
|
$question_element = $element[$key];
|
415
|
|
416
|
// Create a row with the question title.
|
417
|
$row = array(array('data' => _webform_filter_xss($question_element['#title']), 'class' => array('webform-grid-question')));
|
418
|
|
419
|
// Render each radio button in the row.
|
420
|
$radios = form_process_radios($question_element);
|
421
|
foreach (element_children($radios) as $key) {
|
422
|
$radios[$key]['#title'] = $question_element['#title'] . ' - ' . $radios[$key]['#title'];
|
423
|
$radios[$key]['#title_display'] = 'invisible';
|
424
|
$row[] = array('data' => drupal_render($radios[$key]), 'class' => array('checkbox', 'webform-grid-option'));
|
425
|
}
|
426
|
$rows[] = $row;
|
427
|
}
|
428
|
|
429
|
$option_count = count($header) - 1;
|
430
|
return theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('class' => array('webform-grid', 'webform-grid-' . $option_count))));
|
431
|
}
|