root / drupal7 / sites / all / modules / webform / webform.api.php @ ca0757b9
1 | 85ad3d82 | Assos Assos | <?php
|
---|---|---|---|
2 | |||
3 | /**
|
||
4 | * @file
|
||
5 | * Sample hooks demonstrating usage in Webform.
|
||
6 | */
|
||
7 | |||
8 | /**
|
||
9 | * @defgroup webform_hooks Webform Module Hooks
|
||
10 | * @{
|
||
11 | * Webform's hooks enable other modules to intercept events within Webform, such
|
||
12 | * as the completion of a submission or adding validation. Webform's hooks also
|
||
13 | * allow other modules to provide additional components for use within forms.
|
||
14 | */
|
||
15 | |||
16 | /**
|
||
17 | * Define callbacks that can be used as select list options.
|
||
18 | *
|
||
19 | * When users create a select component, they may select a pre-built list of
|
||
20 | * certain options. Webform core provides a few of these lists such as the
|
||
21 | * United States, countries of the world, and days of the week. This hook
|
||
22 | * provides additional lists that may be utilized.
|
||
23 | *
|
||
24 | * @see webform_options_example()
|
||
25 | * @see hook_webform_select_options_info_alter()
|
||
26 | *
|
||
27 | * @return
|
||
28 | * An array of callbacks that can be used for select list options. This array
|
||
29 | * should be keyed by the "name" of the pre-defined list. The values should
|
||
30 | * be an array with the following additional keys:
|
||
31 | * - title: The translated title for this list.
|
||
32 | * - options callback: The name of the function that will return the list.
|
||
33 | * - options arguments: Any additional arguments to send to the callback.
|
||
34 | * - file: Optional. The file containing the options callback, relative to
|
||
35 | * the module root.
|
||
36 | */
|
||
37 | function hook_webform_select_options_info() { |
||
38 | $items = array(); |
||
39 | |||
40 | $items['days'] = array( |
||
41 | 'title' => t('Days of the week'), |
||
42 | 'options callback' => 'webform_options_days', |
||
43 | 'file' => 'includes/webform.options.inc', |
||
44 | ); |
||
45 | |||
46 | return $items; |
||
47 | } |
||
48 | |||
49 | /**
|
||
50 | * Alter the list of select list options provided by Webform and other modules.
|
||
51 | *
|
||
52 | * @see hook_webform_select_options_info().
|
||
53 | */
|
||
54 | function hook_webform_select_options_info_alter(&$items) { |
||
55 | // Remove the days of the week options.
|
||
56 | unset($items['days']); |
||
57 | } |
||
58 | |||
59 | /**
|
||
60 | * This is an example function to demonstrate a webform options callback.
|
||
61 | *
|
||
62 | * This function returns a list of options that Webform may use in a select
|
||
63 | * component. In order to be called, the function name
|
||
64 | * ("webform_options_example" in this case), needs to be specified as a callback
|
||
65 | * in hook_webform_select_options_info().
|
||
66 | *
|
||
67 | * @param $component
|
||
68 | * The Webform component array for the select component being displayed.
|
||
69 | * @param $flat
|
||
70 | * Boolean value indicating whether the returned list needs to be a flat array
|
||
71 | * of key => value pairs. Select components support up to one level of
|
||
72 | * nesting, but when results are displayed, the list needs to be returned
|
||
73 | * without the nesting.
|
||
74 | * @param $filter
|
||
75 | * Boolean value indicating whether the included options should be passed
|
||
76 | * through the _webform_filter_values() function for token replacement (only)
|
||
77 | * needed if your list contains tokens).
|
||
78 | * @param $arguments
|
||
79 | * The "options arguments" specified in hook_webform_select_options_info().
|
||
80 | * @return
|
||
81 | * An array of key => value pairs suitable for a select list's #options
|
||
82 | * FormAPI property.
|
||
83 | */
|
||
84 | function webform_options_example($component, $flat, $filter, $arguments) { |
||
85 | $options = array( |
||
86 | 'one' => t('Pre-built option one'), |
||
87 | 'two' => t('Pre-built option two'), |
||
88 | 'three' => t('Pre-built option three'), |
||
89 | ); |
||
90 | |||
91 | return $options; |
||
92 | } |
||
93 | |||
94 | /**
|
||
95 | * Respond to the loading of Webform submissions.
|
||
96 | *
|
||
97 | * @param $submissions
|
||
98 | * An array of Webform submissions that are being loaded, keyed by the
|
||
99 | * submission ID. Modifications to the submissions are done by reference.
|
||
100 | */
|
||
101 | function hook_webform_submission_load(&$submissions) { |
||
102 | foreach ($submissions as $sid => $submission) { |
||
103 | $submissions[$sid]->new_property = 'foo'; |
||
104 | } |
||
105 | } |
||
106 | |||
107 | /**
|
||
108 | * Modify a Webform submission, prior to saving it in the database.
|
||
109 | *
|
||
110 | * @param $node
|
||
111 | * The Webform node on which this submission was made.
|
||
112 | * @param $submission
|
||
113 | * The Webform submission that is about to be saved to the database.
|
||
114 | */
|
||
115 | function hook_webform_submission_presave($node, &$submission) { |
||
116 | // Update some component's value before it is saved.
|
||
117 | $component_id = 4; |
||
118 | $submission->data[$component_id]['value'][0] = 'foo'; |
||
119 | } |
||
120 | |||
121 | /**
|
||
122 | * Respond to a Webform submission being inserted.
|
||
123 | *
|
||
124 | * Note that this hook is called after a submission has already been saved to
|
||
125 | * the database. If needing to modify the submission prior to insertion, use
|
||
126 | * hook_webform_submission_presave().
|
||
127 | *
|
||
128 | * @param $node
|
||
129 | * The Webform node on which this submission was made.
|
||
130 | * @param $submission
|
||
131 | * The Webform submission that was just inserted into the database.
|
||
132 | */
|
||
133 | function hook_webform_submission_insert($node, $submission) { |
||
134 | // Insert a record into a 3rd-party module table when a submission is added.
|
||
135 | db_insert('mymodule_table')
|
||
136 | ->fields(array(
|
||
137 | 'nid' => $node->nid, |
||
138 | 'sid' => $submission->sid, |
||
139 | 'foo' => 'foo_data', |
||
140 | )) |
||
141 | ->execute(); |
||
142 | } |
||
143 | |||
144 | /**
|
||
145 | * Respond to a Webform submission being updated.
|
||
146 | *
|
||
147 | * Note that this hook is called after a submission has already been saved to
|
||
148 | * the database. If needing to modify the submission prior to updating, use
|
||
149 | * hook_webform_submission_presave().
|
||
150 | *
|
||
151 | * @param $node
|
||
152 | * The Webform node on which this submission was made.
|
||
153 | * @param $submission
|
||
154 | * The Webform submission that was just updated in the database.
|
||
155 | */
|
||
156 | function hook_webform_submission_update($node, $submission) { |
||
157 | // Update a record in a 3rd-party module table when a submission is updated.
|
||
158 | db_update('mymodule_table')
|
||
159 | ->fields(array(
|
||
160 | 'foo' => 'foo_data', |
||
161 | )) |
||
162 | ->condition('nid', $node->nid) |
||
163 | ->condition('sid', $submission->sid) |
||
164 | ->execute(); |
||
165 | } |
||
166 | |||
167 | /**
|
||
168 | * Respond to a Webform submission being deleted.
|
||
169 | *
|
||
170 | * @param $node
|
||
171 | * The Webform node on which this submission was made.
|
||
172 | * @param $submission
|
||
173 | * The Webform submission that was just deleted from the database.
|
||
174 | */
|
||
175 | function hook_webform_submission_delete($node, $submission) { |
||
176 | // Delete a record from a 3rd-party module table when a submission is deleted.
|
||
177 | db_delete('mymodule_table')
|
||
178 | ->condition('nid', $node->nid) |
||
179 | ->condition('sid', $submission->sid) |
||
180 | ->execute(); |
||
181 | } |
||
182 | |||
183 | /**
|
||
184 | * Provide a list of actions that can be executed on a submission.
|
||
185 | *
|
||
186 | * Some actions are displayed in the list of submissions such as edit, view, and
|
||
187 | * delete. All other actions are displayed only when viewing the submission.
|
||
188 | * These additional actions may be specified in this hook. Examples included
|
||
189 | * directly in the Webform module include PDF, print, and resend e-mails. Other
|
||
190 | * modules may extend this list by using this hook.
|
||
191 | *
|
||
192 | * @param $node
|
||
193 | * The Webform node on which this submission was made.
|
||
194 | * @param $submission
|
||
195 | * The Webform submission on which the actions may be performed.
|
||
196 | */
|
||
197 | function hook_webform_submission_actions($node, $submission) { |
||
198 | if (webform_results_access($node)) { |
||
199 | $actions['myaction'] = array( |
||
200 | 'title' => t('Do my action'), |
||
201 | 'href' => 'node/' . $node->nid . '/submission/' . $submission->sid . '/myaction', |
||
202 | 'query' => drupal_get_destination(),
|
||
203 | ); |
||
204 | } |
||
205 | |||
206 | return $actions; |
||
207 | } |
||
208 | |||
209 | /**
|
||
210 | * Alter the display of a Webform submission.
|
||
211 | *
|
||
212 | * This function applies to both e-mails sent by Webform and normal display of
|
||
213 | * submissions when viewing through the adminsitrative interface.
|
||
214 | *
|
||
215 | * @param $renderable
|
||
216 | * The Webform submission in a renderable array, similar to FormAPI's
|
||
217 | * structure. This variable must be passed in by-reference. Important
|
||
218 | * properties of this array include #node, #submission, #email, and #format,
|
||
219 | * which can be used to find the context of the submission that is being
|
||
220 | * rendered.
|
||
221 | */
|
||
222 | function hook_webform_submission_render_alter(&$renderable) { |
||
223 | // Remove page breaks from sent e-mails.
|
||
224 | if (isset($renderable['#email'])) { |
||
225 | foreach (element_children($renderable) as $key) { |
||
226 | if ($renderable[$key]['#component']['type'] == 'pagebreak') { |
||
227 | unset($renderable[$key]); |
||
228 | } |
||
229 | } |
||
230 | } |
||
231 | } |
||
232 | |||
233 | /**
|
||
234 | * Modify a loaded Webform component.
|
||
235 | *
|
||
236 | * IMPORTANT: This hook does not actually exist because components are loaded
|
||
237 | * in bulk as part of webform_node_load(). Use hook_node_load() to modify loaded
|
||
238 | * components when the node is loaded. This example is provided merely to point
|
||
239 | * to hook_node_load().
|
||
240 | *
|
||
241 | * @see hook_nodeapi()
|
||
242 | * @see webform_node_load()
|
||
243 | */
|
||
244 | function hook_webform_component_load() { |
||
245 | // This hook does not exist. Instead use hook_node_load().
|
||
246 | } |
||
247 | |||
248 | /**
|
||
249 | * Modify a Webform component before it is saved to the database.
|
||
250 | *
|
||
251 | * Note that most of the time this hook is not necessary, because Webform will
|
||
252 | * automatically add data to the component based on the component form. Using
|
||
253 | * hook_form_alter() will be sufficient in most cases.
|
||
254 | *
|
||
255 | * @see hook_form_alter()
|
||
256 | * @see webform_component_edit_form()
|
||
257 | *
|
||
258 | * @param $component
|
||
259 | * The Webform component being saved.
|
||
260 | */
|
||
261 | function hook_webform_component_presave(&$component) { |
||
262 | $component['extra']['new_option'] = 'foo'; |
||
263 | } |
||
264 | |||
265 | /**
|
||
266 | * Respond to a Webform component being inserted into the database.
|
||
267 | */
|
||
268 | function hook_webform_component_insert($component) { |
||
269 | // Insert a record into a 3rd-party module table when a component is inserted.
|
||
270 | db_insert('mymodule_table')
|
||
271 | ->fields(array(
|
||
272 | 'nid' => $component['nid'], |
||
273 | 'cid' => $component['cid'], |
||
274 | 'foo' => 'foo_data', |
||
275 | )) |
||
276 | ->execute(); |
||
277 | } |
||
278 | |||
279 | /**
|
||
280 | * Respond to a Webform component being updated in the database.
|
||
281 | */
|
||
282 | function hook_webform_component_update($component) { |
||
283 | // Update a record in a 3rd-party module table when a component is updated.
|
||
284 | db_update('mymodule_table')
|
||
285 | ->fields(array(
|
||
286 | 'foo' => 'foo_data', |
||
287 | )) |
||
288 | ->condition('nid', $component['nid']) |
||
289 | ->condition('cid', $component['cid']) |
||
290 | ->execute(); |
||
291 | } |
||
292 | |||
293 | /**
|
||
294 | * Respond to a Webform component being deleted.
|
||
295 | */
|
||
296 | function hook_webform_component_delete($component) { |
||
297 | // Delete a record in a 3rd-party module table when a component is deleted.
|
||
298 | db_delete('mymodule_table')
|
||
299 | ->condition('nid', $component['nid']) |
||
300 | ->condition('cid', $component['cid']) |
||
301 | ->execute(); |
||
302 | } |
||
303 | |||
304 | 3753f249 | Assos Assos | /**
|
305 | * Alter a Webform submission's header when exported.
|
||
306 | */
|
||
307 | function hook_webform_csv_header_alter(&$header, $component) { |
||
308 | // Use the machine name for component headers, but only for the webform
|
||
309 | // with node 5 and components that are text fields.
|
||
310 | if ($component['nid'] == 5 && $component['type'] == 'textfield') { |
||
311 | $header[2] = $component['form_key']; |
||
312 | } |
||
313 | } |
||
314 | |||
315 | /**
|
||
316 | * Alter a Webform submission's data when exported.
|
||
317 | */
|
||
318 | function hook_webform_csv_data_alter(&$data, $component, $submission) { |
||
319 | // If a value of a field was left blank, use the value from another
|
||
320 | // field.
|
||
321 | if ($component['cid'] == 1 && empty($data)) { |
||
322 | $data = $submission->data[2]['value'][0]; |
||
323 | } |
||
324 | } |
||
325 | |||
326 | 85ad3d82 | Assos Assos | /**
|
327 | * Define components to Webform.
|
||
328 | *
|
||
329 | * @return
|
||
330 | * An array of components, keyed by machine name. Required properties are
|
||
331 | * "label" and "description". The "features" array defines which capabilities
|
||
332 | * the component has, such as being displayed in e-mails or csv downloads.
|
||
333 | * A component like "markup" for example would not show in these locations.
|
||
334 | * The possible features of a component include:
|
||
335 | *
|
||
336 | * - csv
|
||
337 | * - email
|
||
338 | * - email_address
|
||
339 | * - email_name
|
||
340 | * - required
|
||
341 | * - conditional
|
||
342 | * - spam_analysis
|
||
343 | * - group
|
||
344 | *
|
||
345 | * Note that most of these features do not indicate the default state, but
|
||
346 | * determine if the component can have this property at all. Setting
|
||
347 | * "required" to TRUE does not mean that a component's fields will always be
|
||
348 | * required, but instead give the option to the administrator to choose the
|
||
349 | * requiredness. See the example implementation for details on how these
|
||
350 | * features may be set.
|
||
351 | *
|
||
352 | * An optional "file" may be specified to be loaded when the component is
|
||
353 | * needed. A set of callbacks will be established based on the name of the
|
||
354 | * component. All components follow the pattern:
|
||
355 | *
|
||
356 | * _webform_[callback]_[component]
|
||
357 | *
|
||
358 | * Where [component] is the name of the key of the component and [callback] is
|
||
359 | * any of the following:
|
||
360 | *
|
||
361 | * - defaults
|
||
362 | * - edit
|
||
363 | * - render
|
||
364 | * - display
|
||
365 | * - submit
|
||
366 | * - delete
|
||
367 | * - help
|
||
368 | * - theme
|
||
369 | * - analysis
|
||
370 | * - table
|
||
371 | * - csv_headers
|
||
372 | * - csv_data
|
||
373 | *
|
||
374 | * See the sample component implementation for details on each one of these
|
||
375 | * callbacks.
|
||
376 | *
|
||
377 | * @see webform_components()
|
||
378 | */
|
||
379 | function hook_webform_component_info() { |
||
380 | $components = array(); |
||
381 | |||
382 | $components['textfield'] = array( |
||
383 | 'label' => t('Textfield'), |
||
384 | 'description' => t('Basic textfield type.'), |
||
385 | 'features' => array( |
||
386 | // Add content to CSV downloads. Defaults to TRUE.
|
||
387 | 'csv' => TRUE, |
||
388 | |||
389 | // This component supports default values. Defaults to TRUE.
|
||
390 | 'default_value' => FALSE, |
||
391 | |||
392 | // This component supports a description field. Defaults to TRUE.
|
||
393 | 'description' => FALSE, |
||
394 | |||
395 | // Show this component in e-mailed submissions. Defaults to TRUE.
|
||
396 | 'email' => TRUE, |
||
397 | |||
398 | // Allow this component to be used as an e-mail FROM or TO address.
|
||
399 | // Defaults to FALSE.
|
||
400 | 'email_address' => FALSE, |
||
401 | |||
402 | // Allow this component to be used as an e-mail SUBJECT or FROM name.
|
||
403 | // Defaults to FALSE.
|
||
404 | 'email_name' => TRUE, |
||
405 | |||
406 | // This component may be toggled as required or not. Defaults to TRUE.
|
||
407 | 'required' => TRUE, |
||
408 | |||
409 | // This component supports a title attribute. Defaults to TRUE.
|
||
410 | 'title' => FALSE, |
||
411 | |||
412 | // This component has a title that can be toggled as displayed or not.
|
||
413 | 'title_display' => TRUE, |
||
414 | |||
415 | // This component has a title that can be displayed inline.
|
||
416 | 'title_inline' => TRUE, |
||
417 | |||
418 | // If this component can be used as a conditional SOURCE. All components
|
||
419 | // may always be displayed conditionally, regardless of this setting.
|
||
420 | // Defaults to TRUE.
|
||
421 | 'conditional' => TRUE, |
||
422 | |||
423 | // If this component allows other components to be grouped within it
|
||
424 | // (like a fieldset or tabs). Defaults to FALSE.
|
||
425 | 'group' => FALSE, |
||
426 | |||
427 | // If this component can be used for SPAM analysis, usually with Mollom.
|
||
428 | 'spam_analysis' => FALSE, |
||
429 | |||
430 | // If this component saves a file that can be used as an e-mail
|
||
431 | // attachment. Defaults to FALSE.
|
||
432 | 'attachment' => FALSE, |
||
433 | ), |
||
434 | 'file' => 'components/textfield.inc', |
||
435 | ); |
||
436 | |||
437 | return $components; |
||
438 | } |
||
439 | |||
440 | /**
|
||
441 | * Alter the list of available Webform components.
|
||
442 | *
|
||
443 | * @param $components
|
||
444 | * A list of existing components as defined by hook_webform_component_info().
|
||
445 | *
|
||
446 | * @see hook_webform_component_info()
|
||
447 | */
|
||
448 | function hook_webform_component_info_alter(&$components) { |
||
449 | // Completely remove a component.
|
||
450 | unset($components['grid']); |
||
451 | |||
452 | // Change the name of a component.
|
||
453 | $components['textarea']['label'] = t('Text box'); |
||
454 | } |
||
455 | |||
456 | 3753f249 | Assos Assos | /**
|
457 | * Alter the list of Webform component default values.
|
||
458 | *
|
||
459 | * @param $defaults
|
||
460 | * A list of component defaults as defined by _webform_defaults_COMPONENT().
|
||
461 | * @param $type
|
||
462 | * The component type whose defaults are being provided.
|
||
463 | *
|
||
464 | * @see _webform_defaults_component()
|
||
465 | */
|
||
466 | function hook_webform_component_defaults_alter(&$defaults, $type) { |
||
467 | // Alter a default for all component types.
|
||
468 | $defaults['required'] = 1; |
||
469 | |||
470 | // Add a default for a new field added via hook_form_alter() or
|
||
471 | // hook_form_FORM_ID_alter() for all component types.
|
||
472 | $defaults['extra']['added_field'] = t('Added default value'); |
||
473 | |||
474 | // Add or alter defaults for specific component types:
|
||
475 | switch ($type) { |
||
476 | case 'select': |
||
477 | $defaults['extra']['optrand'] = 1; |
||
478 | break;
|
||
479 | |||
480 | case 'textfield': |
||
481 | case 'textarea': |
||
482 | $defaults['extra']['another_added_field'] = t('Another added default value'); |
||
483 | } |
||
484 | } |
||
485 | |||
486 | 85ad3d82 | Assos Assos | /**
|
487 | * Alter access to a Webform submission.
|
||
488 | *
|
||
489 | * @param $node
|
||
490 | * The Webform node on which this submission was made.
|
||
491 | * @param $submission
|
||
492 | * The Webform submission.
|
||
493 | * @param $op
|
||
494 | * The operation to be performed on the submission. Possible values are:
|
||
495 | * - "view"
|
||
496 | * - "edit"
|
||
497 | * - "delete"
|
||
498 | * - "list"
|
||
499 | * @param $account
|
||
500 | * A user account object.
|
||
501 | * @return
|
||
502 | * TRUE if the current user has access to submission,
|
||
503 | * or FALSE otherwise.
|
||
504 | */
|
||
505 | function hook_webform_submission_access($node, $submission, $op = 'view', $account = NULL) { |
||
506 | switch ($op) { |
||
507 | case 'view': |
||
508 | return TRUE; |
||
509 | break;
|
||
510 | case 'edit': |
||
511 | return FALSE; |
||
512 | break;
|
||
513 | case 'delete': |
||
514 | return TRUE; |
||
515 | break;
|
||
516 | case 'list': |
||
517 | return TRUE; |
||
518 | break;
|
||
519 | } |
||
520 | } |
||
521 | |||
522 | /**
|
||
523 | * Determine if a user has access to see the results of a webform.
|
||
524 | *
|
||
525 | * Note in addition to the view access to the results granted here, the $account
|
||
526 | * must also have view access to the Webform node in order to see results.
|
||
527 | *
|
||
528 | * @see webform_results_access().
|
||
529 | *
|
||
530 | * @param $node
|
||
531 | * The Webform node to check access on.
|
||
532 | * @param $account
|
||
533 | * The user account to check access on.
|
||
534 | * @return
|
||
535 | * TRUE or FALSE if the user can access the webform results.
|
||
536 | */
|
||
537 | function hook_webform_results_access($node, $account) { |
||
538 | // Let editors view results of unpublished webforms.
|
||
539 | if ($node->status == 0 && in_array('editor', $account->roles)) { |
||
540 | return TRUE; |
||
541 | } |
||
542 | else {
|
||
543 | return FALSE; |
||
544 | } |
||
545 | } |
||
546 | |||
547 | /**
|
||
548 | * Return an array of files associated with the component.
|
||
549 | *
|
||
550 | * The output of this function will be used to attach files to e-mail messages.
|
||
551 | *
|
||
552 | * @param $component
|
||
553 | * A Webform component array.
|
||
554 | * @param $value
|
||
555 | * An array of information containing the submission result, directly
|
||
556 | * correlating to the webform_submitted_data database schema.
|
||
557 | * @return
|
||
558 | * An array of files, each file is an array with following keys:
|
||
559 | * - filepath: The relative path to the file.
|
||
560 | * - filename: The name of the file including the extension.
|
||
561 | * - filemime: The mimetype of the file.
|
||
562 | * This will result in an array looking something like this:
|
||
563 | * @code
|
||
564 | * array[0] => array(
|
||
565 | * 'filepath' => '/sites/default/files/attachment.txt',
|
||
566 | * 'filename' => 'attachment.txt',
|
||
567 | * 'filemime' => 'text/plain',
|
||
568 | * );
|
||
569 | * @endcode
|
||
570 | */
|
||
571 | function _webform_attachments_component($component, $value) { |
||
572 | $files = array(); |
||
573 | $files[] = (array) file_load($value[0]); |
||
574 | return $files; |
||
575 | } |
||
576 | |||
577 | /**
|
||
578 | * @}
|
||
579 | */
|
||
580 | |||
581 | /**
|
||
582 | * @defgroup webform_component Sample Webform Component
|
||
583 | * @{
|
||
584 | * In each of these examples, the word "component" should be replaced with the,
|
||
585 | * name of the component type (such as textfield or select). These are not
|
||
586 | * actual hooks, but instead samples of how Webform integrates with its own
|
||
587 | * built-in components.
|
||
588 | */
|
||
589 | |||
590 | /**
|
||
591 | * Specify the default properties of a component.
|
||
592 | *
|
||
593 | * @return
|
||
594 | * An array defining the default structure of a component.
|
||
595 | */
|
||
596 | function _webform_defaults_component() { |
||
597 | return array( |
||
598 | 'name' => '', |
||
599 | 'form_key' => NULL, |
||
600 | 'mandatory' => 0, |
||
601 | 'pid' => 0, |
||
602 | 'weight' => 0, |
||
603 | 'extra' => array( |
||
604 | 'options' => '', |
||
605 | 'questions' => '', |
||
606 | 'optrand' => 0, |
||
607 | 'qrand' => 0, |
||
608 | 'description' => '', |
||
609 | ), |
||
610 | ); |
||
611 | } |
||
612 | |||
613 | /**
|
||
614 | * Generate the form for editing a component.
|
||
615 | *
|
||
616 | * Create a set of form elements to be displayed on the form for editing this
|
||
617 | * component. Use care naming the form items, as this correlates directly to the
|
||
618 | * database schema. The component "Name" and "Description" fields are added to
|
||
619 | * every component type and are not necessary to specify here (although they
|
||
620 | * may be overridden if desired).
|
||
621 | *
|
||
622 | * @param $component
|
||
623 | * A Webform component array.
|
||
624 | * @return
|
||
625 | * An array of form items to be displayed on the edit component page
|
||
626 | */
|
||
627 | function _webform_edit_component($component) { |
||
628 | $form = array(); |
||
629 | |||
630 | // Disabling the description if not wanted.
|
||
631 | $form['description'] = array(); |
||
632 | |||
633 | // Most options are stored in the "extra" array, which stores any settings
|
||
634 | // unique to a particular component type.
|
||
635 | $form['extra']['options'] = array( |
||
636 | '#type' => 'textarea', |
||
637 | '#title' => t('Options'), |
||
638 | '#default_value' => $component['extra']['options'], |
||
639 | '#description' => t('Key-value pairs may be entered separated by pipes. i.e. safe_key|Some readable option') . theme('webform_token_help'), |
||
640 | '#cols' => 60, |
||
641 | '#rows' => 5, |
||
642 | '#weight' => -3, |
||
643 | '#required' => TRUE, |
||
644 | ); |
||
645 | return $form; |
||
646 | } |
||
647 | |||
648 | /**
|
||
649 | * Render a Webform component to be part of a form.
|
||
650 | *
|
||
651 | * @param $component
|
||
652 | * A Webform component array.
|
||
653 | * @param $value
|
||
654 | * If editing an existing submission or resuming a draft, this will contain
|
||
655 | * an array of values to be shown instead of the default in the component
|
||
656 | * configuration. This value will always be an array, keyed numerically for
|
||
657 | * each value saved in this field.
|
||
658 | * @param $filter
|
||
659 | * Whether or not to filter the contents of descriptions and values when
|
||
660 | * rendering the component. Values need to be unfiltered to be editable by
|
||
661 | * Form Builder.
|
||
662 | *
|
||
663 | * @see _webform_client_form_add_component()
|
||
664 | */
|
||
665 | function _webform_render_component($component, $value = NULL, $filter = TRUE) { |
||
666 | $form_item = array( |
||
667 | '#type' => 'textfield', |
||
668 | '#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'], |
||
669 | '#required' => $component['mandatory'], |
||
670 | '#weight' => $component['weight'], |
||
671 | '#description' => $filter ? _webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'], |
||
672 | '#default_value' => $filter ? _webform_filter_values($component['value']) : $component['value'], |
||
673 | '#prefix' => '<div class="webform-component-textfield" id="webform-component-' . $component['form_key'] . '">', |
||
674 | '#suffix' => '</div>', |
||
675 | ); |
||
676 | |||
677 | if (isset($value)) { |
||
678 | $form_item['#default_value'] = $value[0]; |
||
679 | } |
||
680 | |||
681 | return $form_item; |
||
682 | } |
||
683 | |||
684 | /**
|
||
685 | * Display the result of a submission for a component.
|
||
686 | *
|
||
687 | * The output of this function will be displayed under the "Results" tab then
|
||
688 | * "Submissions". This should output the saved data in some reasonable manner.
|
||
689 | *
|
||
690 | * @param $component
|
||
691 | * A Webform component array.
|
||
692 | * @param $value
|
||
693 | * An array of information containing the submission result, directly
|
||
694 | * correlating to the webform_submitted_data database table schema.
|
||
695 | * @param $format
|
||
696 | * Either 'html' or 'text'. Defines the format that the content should be
|
||
697 | * returned as. Make sure that returned content is run through check_plain()
|
||
698 | * or other filtering functions when returning HTML.
|
||
699 | * @return
|
||
700 | * A renderable element containing at the very least these properties:
|
||
701 | * - #title
|
||
702 | * - #weight
|
||
703 | * - #component
|
||
704 | * - #format
|
||
705 | * - #value
|
||
706 | * Webform also uses #theme_wrappers to output the end result to the user,
|
||
707 | * which will properly format the label and content for use within an e-mail
|
||
708 | * (such as wrapping the text) or as HTML (ensuring consistent output).
|
||
709 | */
|
||
710 | function _webform_display_component($component, $value, $format = 'html') { |
||
711 | return array( |
||
712 | '#title' => $component['name'], |
||
713 | '#weight' => $component['weight'], |
||
714 | '#theme' => 'webform_display_textfield', |
||
715 | '#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'), |
||
716 | '#post_render' => array('webform_element_wrapper'), |
||
717 | '#field_prefix' => $component['extra']['field_prefix'], |
||
718 | '#field_suffix' => $component['extra']['field_suffix'], |
||
719 | '#component' => $component, |
||
720 | '#format' => $format, |
||
721 | '#value' => isset($value[0]) ? $value[0] : '', |
||
722 | ); |
||
723 | } |
||
724 | |||
725 | /**
|
||
726 | * A hook for changing the input values before saving to the database.
|
||
727 | *
|
||
728 | * Webform expects a component to consist of a single field, or a single array
|
||
729 | * of fields. If you have a component that requires a deeper form tree
|
||
730 | * you must flatten the data into a single array using this callback
|
||
731 | * or by setting #parents on each field to avoid data loss and/or unexpected
|
||
732 | * behavior.
|
||
733 | *
|
||
734 | * Note that Webform will save the result of this function directly into the
|
||
735 | * database.
|
||
736 | *
|
||
737 | * @param $component
|
||
738 | * A Webform component array.
|
||
739 | * @param $value
|
||
740 | * The POST data associated with the user input.
|
||
741 | * @return
|
||
742 | * An array of values to be saved into the database. Note that this should be
|
||
743 | * a numerically keyed array.
|
||
744 | */
|
||
745 | function _webform_submit_component($component, $value) { |
||
746 | // Clean up a phone number into 123-456-7890 format.
|
||
747 | if ($component['extra']['phone_number']) { |
||
748 | $matches = array(); |
||
749 | $number = preg_replace('[^0-9]', $value[0]); |
||
750 | if (strlen($number) == 7) { |
||
751 | $number = substr($number, 0, 3) . '-' . substr($number, 3, 4); |
||
752 | } |
||
753 | else {
|
||
754 | $number = substr($number, 0, 3) . '-' . substr($number, 3, 3) . '-' . substr($number, 6, 4); |
||
755 | } |
||
756 | } |
||
757 | |||
758 | $value[0] = $number; |
||
759 | return $value; |
||
760 | } |
||
761 | |||
762 | /**
|
||
763 | * Delete operation for a component or submission.
|
||
764 | *
|
||
765 | * @param $component
|
||
766 | * A Webform component array.
|
||
767 | * @param $value
|
||
768 | * An array of information containing the submission result, directly
|
||
769 | * correlating to the webform_submitted_data database schema.
|
||
770 | */
|
||
771 | function _webform_delete_component($component, $value) { |
||
772 | // Delete corresponding files when a submission is deleted.
|
||
773 | ca0757b9 | Assos Assos | if (!empty($value[0]) && ($file = webform_get_file($value[0]))) { |
774 | file_usage_delete($file, 'webform'); |
||
775 | file_delete($file);
|
||
776 | 85ad3d82 | Assos Assos | } |
777 | } |
||
778 | |||
779 | /**
|
||
780 | * Module specific instance of hook_help().
|
||
781 | *
|
||
782 | * This allows each Webform component to add information into hook_help().
|
||
783 | */
|
||
784 | function _webform_help_component($section) { |
||
785 | switch ($section) { |
||
786 | case 'admin/config/content/webform#grid_description': |
||
787 | return t('Allows creation of grid questions, denoted by radio buttons.'); |
||
788 | } |
||
789 | } |
||
790 | |||
791 | /**
|
||
792 | * Module specific instance of hook_theme().
|
||
793 | *
|
||
794 | * This allows each Webform component to add information into hook_theme(). If
|
||
795 | * you specify a file to include, you must define the path to the module that
|
||
796 | * this file belongs to.
|
||
797 | */
|
||
798 | function _webform_theme_component() { |
||
799 | return array( |
||
800 | 'webform_grid' => array( |
||
801 | 'render element' => 'element', |
||
802 | 'file' => 'components/grid.inc', |
||
803 | 'path' => drupal_get_path('module', 'webform'), |
||
804 | ), |
||
805 | 'webform_display_grid' => array( |
||
806 | 'render element' => 'element', |
||
807 | 'file' => 'components/grid.inc', |
||
808 | 'path' => drupal_get_path('module', 'webform'), |
||
809 | ), |
||
810 | ); |
||
811 | } |
||
812 | |||
813 | /**
|
||
814 | * Calculate and returns statistics about results for this component.
|
||
815 | *
|
||
816 | * This takes into account all submissions to this webform. The output of this
|
||
817 | * function will be displayed under the "Results" tab then "Analysis".
|
||
818 | *
|
||
819 | * @param $component
|
||
820 | * An array of information describing the component, directly correlating to
|
||
821 | * the webform_component database schema.
|
||
822 | * @param $sids
|
||
823 | * An optional array of submission IDs (sid). If supplied, the analysis will
|
||
824 | * be limited to these sids.
|
||
825 | * @param $single
|
||
826 | * Boolean flag determining if the details about a single component are being
|
||
827 | * shown. May be used to provided detailed information about a single
|
||
828 | * component's analysis, such as showing "Other" options within a select list.
|
||
829 | * @return
|
||
830 | * An array of data rows, each containing a statistic for this component's
|
||
831 | * submissions.
|
||
832 | */
|
||
833 | function _webform_analysis_component($component, $sids = array(), $single = FALSE) { |
||
834 | // Generate the list of options and questions.
|
||
835 | $options = _webform_select_options_from_text($component['extra']['options'], TRUE); |
||
836 | $questions = _webform_select_options_from_text($component['extra']['questions'], TRUE); |
||
837 | |||
838 | // Generate a lookup table of results.
|
||
839 | $query = db_select('webform_submitted_data', 'wsd') |
||
840 | ->fields('wsd', array('no', 'data')) |
||
841 | ->condition('nid', $component['nid']) |
||
842 | ->condition('cid', $component['cid']) |
||
843 | ->condition('data', '', '<>') |
||
844 | ->groupBy('no')
|
||
845 | ->groupBy('data');
|
||
846 | $query->addExpression('COUNT(sid)', 'datacount'); |
||
847 | |||
848 | if (count($sids)) { |
||
849 | $query->condition('sid', $sids, 'IN'); |
||
850 | } |
||
851 | |||
852 | $result = $query->execute(); |
||
853 | $counts = array(); |
||
854 | foreach ($result as $data) { |
||
855 | $counts[$data->no][$data->data] = $data->datacount; |
||
856 | } |
||
857 | |||
858 | // Create an entire table to be put into the returned row.
|
||
859 | $rows = array(); |
||
860 | $header = array(''); |
||
861 | |||
862 | // Add options as a header row.
|
||
863 | foreach ($options as $option) { |
||
864 | $header[] = $option; |
||
865 | } |
||
866 | |||
867 | // Add questions as each row.
|
||
868 | foreach ($questions as $qkey => $question) { |
||
869 | $row = array($question); |
||
870 | foreach ($options as $okey => $option) { |
||
871 | $row[] = !empty($counts[$qkey][$okey]) ? $counts[$qkey][$okey] : 0; |
||
872 | } |
||
873 | $rows[] = $row; |
||
874 | } |
||
875 | $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('class' => array('webform-grid')))); |
||
876 | |||
877 | return array(array(array('data' => $output, 'colspan' => 2))); |
||
878 | } |
||
879 | |||
880 | /**
|
||
881 | * Return the result of a component value for display in a table.
|
||
882 | *
|
||
883 | * The output of this function will be displayed under the "Results" tab then
|
||
884 | * "Table".
|
||
885 | *
|
||
886 | * @param $component
|
||
887 | * A Webform component array.
|
||
888 | * @param $value
|
||
889 | * An array of information containing the submission result, directly
|
||
890 | * correlating to the webform_submitted_data database schema.
|
||
891 | * @return
|
||
892 | * Textual output formatted for human reading.
|
||
893 | */
|
||
894 | function _webform_table_component($component, $value) { |
||
895 | $questions = array_values(_webform_component_options($component['extra']['questions'])); |
||
896 | $output = ''; |
||
897 | // Set the value as a single string.
|
||
898 | if (is_array($value)) { |
||
899 | foreach ($value as $item => $value) { |
||
900 | if ($value !== '') { |
||
901 | $output .= $questions[$item] . ': ' . check_plain($value) . '<br />'; |
||
902 | } |
||
903 | } |
||
904 | } |
||
905 | else {
|
||
906 | $output = check_plain(!isset($value['0']) ? '' : $value['0']); |
||
907 | } |
||
908 | return $output; |
||
909 | } |
||
910 | |||
911 | /**
|
||
912 | * Return the header for this component to be displayed in a CSV file.
|
||
913 | *
|
||
914 | * The output of this function will be displayed under the "Results" tab then
|
||
915 | * "Download".
|
||
916 | *
|
||
917 | * @param $component
|
||
918 | * A Webform component array.
|
||
919 | * @param $export_options
|
||
920 | * An array of options that may configure export of this field.
|
||
921 | * @return
|
||
922 | * An array of data to be displayed in the first three rows of a CSV file, not
|
||
923 | * including either prefixed or trailing commas.
|
||
924 | */
|
||
925 | function _webform_csv_headers_component($component, $export_options) { |
||
926 | $header = array(); |
||
927 | $header[0] = array(''); |
||
928 | $header[1] = array($component['name']); |
||
929 | $items = _webform_component_options($component['extra']['questions']); |
||
930 | $count = 0; |
||
931 | foreach ($items as $key => $item) { |
||
932 | // Empty column per sub-field in main header.
|
||
933 | if ($count != 0) { |
||
934 | $header[0][] = ''; |
||
935 | $header[1][] = ''; |
||
936 | } |
||
937 | // The value for this option.
|
||
938 | $header[2][] = $item; |
||
939 | $count++;
|
||
940 | } |
||
941 | |||
942 | return $header; |
||
943 | } |
||
944 | |||
945 | /**
|
||
946 | * Format the submitted data of a component for CSV downloading.
|
||
947 | *
|
||
948 | * The output of this function will be displayed under the "Results" tab then
|
||
949 | * "Download".
|
||
950 | *
|
||
951 | * @param $component
|
||
952 | * A Webform component array.
|
||
953 | * @param $export_options
|
||
954 | * An array of options that may configure export of this field.
|
||
955 | * @param $value
|
||
956 | * An array of information containing the submission result, directly
|
||
957 | * correlating to the webform_submitted_data database schema.
|
||
958 | * @return
|
||
959 | * An array of items to be added to the CSV file. Each value within the array
|
||
960 | * will be another column within the file. This function is called once for
|
||
961 | * every row of data.
|
||
962 | */
|
||
963 | function _webform_csv_data_component($component, $export_options, $value) { |
||
964 | $questions = array_keys(_webform_select_options($component['extra']['questions'])); |
||
965 | $return = array(); |
||
966 | foreach ($questions as $key => $question) { |
||
967 | $return[] = isset($value[$key]) ? $value[$key] : ''; |
||
968 | } |
||
969 | return $return; |
||
970 | } |
||
971 | |||
972 | /**
|
||
973 | * @}
|
||
974 | */ |