| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: webform_hooks.php,v 1.9.2.8 2010/09/10 17:42:23 quicksketch Exp $ 3 4 /** 5 * @file 6 * Sample hooks demonstrating usage in Webform. 7 */ 8 9 /** 10 * @defgroup webform_hooks Webform Module Hooks 11 * @{ 12 * Webform's hooks enable other modules to intercept events within Webform, such 13 * as the completion of a submission or adding validation. Webform's hooks also 14 * allow other modules to provide additional components for use within forms. 15 */ 16 17 /** 18 * Define callbacks that can be used as select list options. 19 * 20 * @return 21 * An array of callbacks that can be used for select list options. This array 22 * should be keyed by the "name" of the pre-defined list. The values should 23 * be an array with the following additional keys: 24 * - title: The translated title for this list. 25 * - options callback: The name of the function that will return the list. 26 * - options arguments: Any additional arguments to send to the callback. 27 * - file: Optional. The file containing the options callback, relative to 28 * the module root. 29 */ 30 function hook_webform_select_options_info() { 31 $items = array(); 32 33 $items['days'] = array( 34 'title' => t('Days of the week'), 35 'options callback' => 'webform_options_days', 36 'file' => 'includes/webform.options.inc', 37 ); 38 39 return $items; 40 } 41 42 /** 43 * Respond to the loading of Webform submissions. 44 * 45 * @param $submissions 46 * An array of Webform submissions that are being loaded, keyed by the 47 * submission ID. Modifications to the submissions are done by reference. 48 */ 49 function hook_webform_submission_load(&$submissions) { 50 foreach ($submissions as $sid => $submission) { 51 $submissions[$sid]->new_property = 'foo'; 52 } 53 } 54 55 /** 56 * Modify a Webform submission, prior to saving it in the database. 57 * 58 * @param $node 59 * The Webform node on which this submission was made. 60 * @param $submission 61 * The Webform submission that is about to be saved to the database. 62 */ 63 function hook_webform_submission_presave($node, &$submission) { 64 // Update some component's value before it is saved. 65 $component_id = 4; 66 $submission->data[$component_id]['value'][0] = 'foo'; 67 } 68 69 /** 70 * Respond to a Webform submission being inserted. 71 * 72 * Note that this hook is called after a submission has already been saved to 73 * the database. If needing to modify the submission prior to insertion, use 74 * hook_webform_submission_presave(). 75 * 76 * @param $node 77 * The Webform node on which this submission was made. 78 * @param $submission 79 * The Webform submission that was just inserted into the database. 80 */ 81 function hook_webform_submission_insert($node, $submission) { 82 // Insert a record into a 3rd-party module table when a submission is added. 83 db_query("INSERT INTO {mymodule_table} nid = %d, sid = %d, foo = '%s'", $node->nid, $submission->sid, 'foo_data'); 84 } 85 86 /** 87 * Respond to a Webform submission being updated. 88 * 89 * Note that this hook is called after a submission has already been saved to 90 * the database. If needing to modify the submission prior to updating, use 91 * hook_webform_submission_presave(). 92 * 93 * @param $node 94 * The Webform node on which this submission was made. 95 * @param $submission 96 * The Webform submission that was just updated in the database. 97 */ 98 function hook_webform_submission_update($node, $submission) { 99 // Update a record in a 3rd-party module table when a submission is updated. 100 db_query("UPDATE {mymodule_table} SET (foo) VALUES ('%s') WHERE nid = %d, sid = %d", 'foo_data', $node->nid, $submission->sid); 101 } 102 103 /** 104 * Respond to a Webform submission being deleted. 105 * 106 * @param $node 107 * The Webform node on which this submission was made. 108 * @param $submission 109 * The Webform submission that was just deleted from the database. 110 */ 111 function hook_webform_submission_delete($node, $submission) { 112 // Delete a record from a 3rd-party module table when a submission is deleted. 113 db_query("DELETE FROM {mymodule_table} WHERE nid = %d, sid = %d", $node->nid, $submission->sid); 114 } 115 116 /** 117 * Alter the display of a Webform submission. 118 * 119 * This function applies to both e-mails sent by Webform and normal display of 120 * submissions when viewing through the adminsitrative interface. 121 * 122 * @param $renderable 123 * The Webform submission in a renderable array, similar to FormAPI's 124 * structure. This variable must be passed in by-reference. Important 125 * properties of this array include #node, #submission, #email, and #format, 126 * which can be used to find the context of the submission that is being 127 * rendered. 128 */ 129 function hook_webform_submission_render_alter(&$renderable) { 130 // Remove page breaks from sent e-mails. 131 if (isset($renderable['#email'])) { 132 foreach (element_children($renderable) as $key) { 133 if ($renderable[$key]['#component']['type'] == 'pagebreak') { 134 unset($renderable[$key]); 135 } 136 } 137 } 138 } 139 140 /** 141 * Modify a loaded Webform component. 142 * 143 * IMPORTANT: This hook does not actually exist because components are loaded 144 * in bulk as part of webform_node_load(). Use hook_nodeapi() to modify loaded 145 * components when the node is loaded. This example is provided merely to point 146 * to hook_nodeapi(). 147 * 148 * @see hook_nodeapi() 149 * @see webform_node_load() 150 */ 151 function hook_webform_component_load() { 152 // This hook does not exist. Instead use hook_nodeapi(). 153 } 154 155 /** 156 * Modify a Webform component before it is saved to the database. 157 * 158 * Note that most of the time this hook is not necessary, because Webform will 159 * automatically add data to the component based on the component form. Using 160 * hook_form_alter() will be sufficient in most cases. 161 * 162 * @see hook_form_alter() 163 * @see webform_component_edit_form() 164 * 165 * @param $component 166 * The Webform component being saved. 167 */ 168 function hook_webform_component_presave(&$component) { 169 $component['extra']['new_option'] = 'foo'; 170 } 171 172 /** 173 * Respond to a Webform component being inserted into the database. 174 */ 175 function hook_webform_component_insert($component) { 176 // Insert a record into a 3rd-party module table when a component is inserted. 177 db_query("INSERT INTO {mymodule_table} (nid, cid) VALUES (%d, %d)", $component['nid'], $component['cid']); 178 } 179 180 /** 181 * Respond to a Webform component being updated in the database. 182 */ 183 function hook_webform_component_update($component) { 184 // Update a record in a 3rd-party module table when a component is updated. 185 db_query('UPDATE {mymodule_table} SET value "%s" WHERE nid = %d AND cid = %d)', 'foo', $component['nid'], $component['cid']); 186 } 187 188 /** 189 * Respond to a Webform component being deleted. 190 */ 191 function hook_webform_component_delete($component) { 192 // Delete a record in a 3rd-party module table when a component is deleted. 193 db_query('DELETE FROM {mymodule_table} WHERE nid = %d AND cid = %d)', $component['nid'], $component['cid']); 194 } 195 196 /** 197 * Define components to Webform. 198 * 199 * @return 200 * An array of components, keyed by machine name. Required properties are 201 * "label" and "description". The "features" array defines which capabilities 202 * the component has, such as being displayed in e-mails or csv downloads. 203 * A component like "markup" for example would not show in these locations. 204 * The possible features of a component include: 205 * 206 * - csv 207 * - email 208 * - email_address 209 * - email_name 210 * - required 211 * - conditional 212 * - spam_analysis 213 * - group 214 * 215 * Note that these features do not indicate the default state, but determine 216 * if the component can have this property at all. Setting "required" to TRUE 217 * does not mean that a field will always be required, but instead give the 218 * option to the administrator to choose the requiredness. See the example 219 * implementation for details on how these features may be set. 220 * 221 * An optional "file" may be specified to be loaded when the component is 222 * needed. A set of callbacks will be established based on the name of the 223 * component. All components follow the pattern: 224 * 225 * _webform_[callback]_[component] 226 * 227 * Where [component] is the name of the key of the component and [callback] is 228 * any of the following: 229 * 230 * - defaults 231 * - theme 232 * - edit 233 * - delete 234 * - render 235 * - display 236 * - analysis 237 * - table 238 * - csv_headers 239 * - csv_data 240 * 241 * See the sample component implementation for details on each one of these 242 * callbacks. 243 * 244 * @see webform_component 245 */ 246 function hook_webform_component_info() { 247 $components = array(); 248 249 $components['textfield'] = array( 250 'label' => t('Textfield'), 251 'description' => t('Basic textfield type.'), 252 'features' => array( 253 // Add content to CSV downloads. Defaults to TRUE. 254 'csv' => TRUE, 255 // Show this field in e-mailed submissions. Defaults to TRUE. 256 'email' => TRUE, 257 // Allow this field to be used as an e-mail FROM or TO address. Defaults 258 // to FALSE. 259 'email_address' => FALSE, 260 // Allow this field to be used as an e-mail SUBJECT or FROM name. Defaults 261 // to FALSE. 262 'email_name' => TRUE, 263 // This field may be toggled as required or not. Defaults to TRUE. 264 'required' => TRUE, 265 // If this field can be used as a conditional SOURCE. All fields may 266 // always be displayed conditionally, regardless of this setting. 267 // Defaults to TRUE. 268 'conditonal' => TRUE, 269 // If this field allows other fields to be grouped within it (like a 270 // fieldset or tabs). Defaults to FALSE. 271 'group' => FALSE, 272 // If this field saves a file that can be used as an e-mail attachment. 273 // Defaults to FALSE. 274 'attachment' => FALSE, 275 ), 276 'file' => 'components/textfield.inc', 277 ); 278 279 return $components; 280 } 281 282 /** 283 * Alter the list of available Webform components. 284 * 285 * @param $components 286 * A list of existing components as defined by hook_webform_component_info(). 287 * 288 * @see hook_webform_component_info() 289 */ 290 function hook_webform_component_info_alter(&$components) { 291 // Completely remove a component. 292 unset($components['grid']); 293 294 // Change the name of a component. 295 $components['textarea']['label'] = t('Text box'); 296 } 297 298 /** 299 * @} 300 */ 301 302 /** 303 * @defgroup webform_component Sample Webform Component 304 * @{ 305 * In each of these examples, the word "component" should be replaced with the, 306 * name of the component type (such as textfield or select). These are not 307 * actual hooks, but instead samples of how Webform integrates with its own 308 * built-in components. 309 */ 310 311 /** 312 * Specify the default properties of a component. 313 * 314 * @return 315 * An array defining the default structure of a component. 316 */ 317 function _webform_defaults_component() { 318 return array( 319 'name' => '', 320 'form_key' => NULL, 321 'email' => 1, 322 'mandatory' => 0, 323 'pid' => 0, 324 'weight' => 0, 325 'extra' => array( 326 'options' => '', 327 'questions' => '', 328 'optrand' => 0, 329 'qrand' => 0, 330 'description' => '', 331 ), 332 ); 333 } 334 335 /** 336 * Generate the form for editing a component. 337 * 338 * Create a set of form elements to be displayed on the form for editing this 339 * component. Use care naming the form items, as this correlates directly to the 340 * database schema. The component "Name" and "Description" fields are added to 341 * every component type and are not necessary to specify here (although they 342 * may be overridden if desired). 343 * 344 * @param $component 345 * A Webform component array. 346 * @return 347 * An array of form items to be displayed on the edit component page 348 */ 349 function _webform_edit_component($component) { 350 $form = array(); 351 352 // Disabling the description if not wanted. 353 $form['description'] = array(); 354 355 // Most options are stored in the "extra" array, which stores any settings 356 // unique to a particular component type. 357 $form['extra']['options'] = array( 358 '#type' => 'textarea', 359 '#title' => t('Options'), 360 '#default_value' => $component['extra']['options'], 361 '#description' => t('Key-value pairs may be entered separated by pipes. i.e. safe_key|Some readable option') . theme('webform_token_help'), 362 '#cols' => 60, 363 '#rows' => 5, 364 '#weight' => -3, 365 '#required' => TRUE, 366 ); 367 return $form; 368 } 369 370 /** 371 * Render a Webform component to be part of a form. 372 * 373 * @param $component 374 * A Webform component array. 375 * @param $value 376 * If editing an existing submission or resuming a draft, this will contain 377 * an array of values to be shown instead of the default in the component 378 * configuration. This value will always be an array, keyed numerically for 379 * each value saved in this field. 380 */ 381 function _webform_render_component($component, $value = NULL) { 382 $form_item = array( 383 '#type' => 'textfield', 384 '#title' => $component['name'], 385 '#required' => $component['mandatory'], 386 '#weight' => $component['weight'], 387 '#description' => _webform_filter_descriptions($component['extra']['description']), 388 '#default_value' => $component['value'], 389 '#prefix' => '<div class="webform-component-'. $component['type'] .'" id="webform-component-'. $component['form_key'] .'">', 390 '#suffix' => '</div>', 391 ); 392 393 if (isset($value)) { 394 $form_item['#default_value'] = $value[0]; 395 } 396 397 return $form_item; 398 } 399 400 /** 401 * Display the result of a submission for a component. 402 * 403 * The output of this function will be displayed under the "Results" tab then 404 * "Submissions". This should output the saved data in some reasonable manner. 405 * 406 * @param $component 407 * A Webform component array. 408 * @param $value 409 * An array of information containing the submission result, directly 410 * correlating to the webform_submitted_data database table schema. 411 * @param $format 412 * Either 'html' or 'text'. Defines the format that the content should be 413 * returned as. Make sure that returned content is run through check_plain() 414 * or other filtering functions when returning HTML. 415 * @return 416 * A renderable element containing at the very least these properties: 417 * - #title 418 * - #weight 419 * - #component 420 * - #format 421 * - #value 422 * Webform also uses #theme_wrappers to output the end result to the user, 423 * which will properly format the label and content for use within an e-mail 424 * (such as wrapping the text) or as HTML (ensuring consistent output). 425 */ 426 function _webform_display_component($component, $value, $format = 'html') { 427 return array( 428 '#title' => $component['name'], 429 '#weight' => $component['weight'], 430 '#theme' => 'webform_display_textfield', 431 '#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'), 432 '#post_render' => array('webform_element_wrapper'), 433 '#field_prefix' => $component['extra']['field_prefix'], 434 '#field_suffix' => $component['extra']['field_suffix'], 435 '#component' => $component, 436 '#format' => $format, 437 '#value' => isset($value[0]) ? $value[0] : '', 438 ); 439 } 440 441 /** 442 * A hook for changing the input values before saving to the database. 443 * 444 * Note that Webform will save the result of this function directly into the 445 * database. 446 * 447 * @param $component 448 * A Webform component array. 449 * @param $value 450 * The POST data associated with the user input. 451 * @return 452 * An array of values to be saved into the database. Note that this should be 453 * a numerically keyed array. 454 */ 455 function _webform_submit_component($component, $value) { 456 // Clean up a phone number into 123-456-7890 format. 457 if ($component['extra']['phone_number']) { 458 $matches = array(); 459 $number = preg_replace('[^0-9]', $value[0]); 460 if (strlen($number) == 7) { 461 $number = substr($number, 0, 3) . '-' . substr($number, 3, 4); 462 } 463 else { 464 $number = substr($number, 0, 3) . '-' . substr($number, 3, 3) . '-' . substr($number, 6, 4); 465 } 466 } 467 468 $value[0] = $number; 469 return $value; 470 } 471 472 /** 473 * Delete operation for a component or submission. 474 * 475 * @param $component 476 * A Webform component array. 477 * @param $value 478 * An array of information containing the submission result, directly 479 * correlating to the webform_submitted_data database schema. 480 */ 481 function _webform_delete_component($component, $value) { 482 // Delete corresponding files when a submission is deleted. 483 $filedata = unserialize($value['0']); 484 if (isset($filedata['filepath']) && is_file($filedata['filepath'])) { 485 unlink($filedata['filepath']); 486 db_query("DELETE FROM {files} WHERE filepath = '%s'", $filedata['filepath']); 487 } 488 } 489 490 /** 491 * Module specific instance of hook_help(). 492 * 493 * This allows each Webform component to add information into hook_help(). 494 */ 495 function _webform_help_component($section) { 496 switch ($section) { 497 case 'admin/settings/webform#grid_description': 498 return t('Allows creation of grid questions, denoted by radio buttons.'); 499 } 500 } 501 502 /** 503 * Module specific instance of hook_theme(). 504 * 505 * This allows each Webform component to add information into hook_theme(). 506 */ 507 function _webform_theme_component() { 508 return array( 509 'webform_grid' => array( 510 'arguments' => array('grid_element' => NULL), 511 ), 512 'webform_mail_grid' => array( 513 'arguments' => array('component' => NULL, 'value' => NULL), 514 ), 515 ); 516 } 517 518 /** 519 * Calculate and returns statistics about results for this component. 520 * 521 * This takes into account all submissions to this webform. The output of this 522 * function will be displayed under the "Results" tab then "Analysis". 523 * 524 * @param $component 525 * An array of information describing the component, directly correlating to 526 * the webform_component database schema. 527 * @param $sids 528 * An optional array of submission IDs (sid). If supplied, the analysis will 529 * be limited to these sids. 530 * @param $single 531 * Boolean flag determining if the details about a single component are being 532 * shown. May be used to provided detailed information about a single 533 * component's analysis, such as showing "Other" options within a select list. 534 * @return 535 * An array of data rows, each containing a statistic for this component's 536 * submissions. 537 */ 538 function _webform_analysis_component($component, $sids = array(), $single = FALSE) { 539 // Generate the list of options and questions. 540 $options = _webform_component_options($component['extra']['options']); 541 $questions = array_values(_webform_component_options($component['extra']['questions'])); 542 543 // Generate a lookup table of results. 544 $placeholders = count($sids) ? array_fill(0, count($sids), "'%s'") : array(); 545 $sidfilter = count($sids) ? " AND sid in (".implode(",", $placeholders).")" : ""; 546 $query = 'SELECT no, data, count(data) as datacount '. 547 ' FROM {webform_submitted_data} '. 548 ' WHERE nid = %d '. 549 ' AND cid = %d '. 550 " AND data != '' ". $sidfilter . 551 ' GROUP BY no, data'; 552 $result = db_query($query, array_merge(array($component['nid'], $component['cid']), $sids)); 553 $counts = array(); 554 while ($data = db_fetch_object($result)) { 555 $counts[$data->no][$data->data] = $data->datacount; 556 } 557 558 // Create an entire table to be put into the returned row. 559 $rows = array(); 560 $header = array(''); 561 562 // Add options as a header row. 563 foreach ($options as $option) { 564 $header[] = $option; 565 } 566 567 // Add questions as each row. 568 foreach ($questions as $qkey => $question) { 569 $row = array($question); 570 foreach ($options as $okey => $option) { 571 $row[] = !empty($counts[$qkey][$okey]) ? $counts[$qkey][$okey] : 0; 572 } 573 $rows[] = $row; 574 } 575 $output = theme('table', $header, $rows, array('class' => 'webform-grid')); 576 577 return array(array(array('data' => $output, 'colspan' => 2))); 578 } 579 580 /** 581 * Return the result of a component value for display in a table. 582 * 583 * The output of this function will be displayed under the "Results" tab then 584 * "Table". 585 * 586 * @param $component 587 * A Webform component array. 588 * @param $value 589 * An array of information containing the submission result, directly 590 * correlating to the webform_submitted_data database schema. 591 * @return 592 * Textual output formatted for human reading. 593 */ 594 function _webform_table_component($component, $value) { 595 $questions = array_values(_webform_component_options($component['extra']['questions'])); 596 $output = ''; 597 // Set the value as a single string. 598 if (is_array($value)) { 599 foreach ($value as $item => $value) { 600 if ($value !== '') { 601 $output .= $questions[$item] .': '. check_plain($value) .'<br />'; 602 } 603 } 604 } 605 else { 606 $output = check_plain(!isset($value['0']) ? '' : $value['0']); 607 } 608 return $output; 609 } 610 611 /** 612 * Return the header for this component to be displayed in a CSV file. 613 * 614 * The output of this function will be displayed under the "Results" tab then 615 * "Download". 616 * 617 * @param $component 618 * A Webform component array. 619 * @param $export_options 620 * An array of options that may configure export of this field. 621 * @return 622 * An array of data to be displayed in the first three rows of a CSV file, not 623 * including either prefixed or trailing commas. 624 */ 625 function _webform_csv_headers_component($component, $export_options) { 626 $header = array(); 627 $header[0] = array(''); 628 $header[1] = array($component['name']); 629 $items = _webform_component_options($component['extra']['questions']); 630 $count = 0; 631 foreach ($items as $key => $item) { 632 // Empty column per sub-field in main header. 633 if ($count != 0) { 634 $header[0][] = ''; 635 $header[1][] = ''; 636 } 637 // The value for this option. 638 $header[2][] = $item; 639 $count++; 640 } 641 642 return $header; 643 } 644 645 /** 646 * Format the submitted data of a component for CSV downloading. 647 * 648 * The output of this function will be displayed under the "Results" tab then 649 * "Download". 650 * 651 * @param $component 652 * A Webform component array. 653 * @param $export_options 654 * An array of options that may configure export of this field. 655 * @param $value 656 * An array of information containing the submission result, directly 657 * correlating to the webform_submitted_data database schema. 658 * @return 659 * An array of items to be added to the CSV file. Each value within the array 660 * will be another column within the file. This function is called once for 661 * every row of data. 662 */ 663 function _webform_csv_data_component($component, $export_options, $value) { 664 $questions = array_keys(_webform_select_options($component['extra']['questions'])); 665 $return = array(); 666 foreach ($questions as $key => $question) { 667 $return[] = isset($value[$key]) ? $value[$key] : ''; 668 } 669 return $return; 670 } 671 672 /** 673 * @} 674 */
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |