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