Project

General

Profile

Revision 389fb945

Added by Assos Assos over 4 years ago

Weekly update of contrib modules

View differences:

drupal7/sites/all/modules/webform/README.md
1
Description
2
-----------
1
# Webform
2

  
3
## Description
4

  
3 5
This module adds a webform content type to your Drupal site.
4 6
A webform can be a questionnaire, contact or request form. These can be used
5 7
by visitor to make contact or to enable a more complex survey than polls
6 8
provide. Submissions from a webform are saved in a database table and
7 9
can optionally be mailed to e-mail addresses upon submission.
8 10

  
9
Requirements
10
------------
11
Drupal 7.x
12
See https://www.drupal.org/project/webform for additional requirements.
11
## Installation
13 12

  
14
Installation
15
------------
16 13
1. Copy the entire webform directory the Drupal sites/all/modules directory.
17 14

  
18 15
2. Login as an administrator. Enable the module in the "Administer" -> "Modules"
......
22 19

  
23 20
4. Create a webform node at node/add/webform.
24 21

  
25
Upgrading from previous versions
26
--------------------------------
22
## Upgrading from previous versions
23

  
27 24
Note that you must be running the latest 3.x version of Webform (for either
28 25
Drupal 6 or Drupal 7) before upgrading to Webform 4.x.
29 26

  
......
46 43

  
47 44
4. Run update.php (at http://www.example.com/update.php).
48 45

  
49
Support
50
-------
46
## Support
47

  
51 48
Please use the issue queue for filing bugs with this module at
52 49
http://drupal.org/project/issues/webform
drupal7/sites/all/modules/webform/THEMING.md
1
Overview
2
--------
1
# Theming Webform
2

  
3
## Overview
4

  
3 5
Webform supports theming similar to the CCK or Views modules. Any webform may be
4 6
themed on the server side, though doing so may require a reasonable amount of
5 7
knowledge about the Drupal Form API. More information about the Form API may be
6 8
found at: http://api.drupal.org/api/file/developer/topics/forms_api.html
7 9

  
8
Theme submission e-mails
9
-----------------------
10
## Theme submission e-mails
11

  
10 12
The default e-mails sent by webform are fairly basic. If you like, you may
11 13
customize the display of e-mails sent by each individual webform.
12 14

  
......
29 31

  
30 32
- To get a better idea of what variables are available to you, you can include
31 33
  the print_r function in your email. Simply include the line:
32

  
34
  ```
33 35
  <?php print_r($submission) ?>
34

  
36
  ```
35 37
  to get a listing of all the available fields you can use in your mail.
36 38

  
37 39
- Advanced Webform e-mail Theming: Theming the e-mail headers may also be done
......
39 41
  Just copy the code out of webform.module and change as necessary in your
40 42
  template.php file. This allows you to customize the e-mail headers.
41 43

  
42
Theme the confirmation page
43
---------------------------
44
## Theme the confirmation page
44 45

  
45 46
After a user submits a webform, they are directed to a page that contains the
46 47
confirmation message set in the webform node settings (assuming the form doesn't
......
55 56
- Open the new file and change it's contents to the your liking. Here's an
56 57
  example that inserts some additional HTML around the confirmation message and
57 58
  gives links to edit the submission.
58

  
59
  ```
59 60
  <?php /* Begin sample webform confirmation page */ ?>
60

  
61 61
  <div class="confirmation-message">
62 62
    <?php print $confirmation_message ?>
63 63
  </div>
64

  
65 64
  <ul>
66 65
    <li><a href="<?php print url('node/' . $node->nid . '/submission/' . $sid)?>">View your submission</a></li>
67 66
    <li><a href="<?php print url('node/' . $node->nid . '/submission/' . $sid . '/edit')?>">Edit your submission</a></li>
68 67
  </ul>
69

  
70 68
  <?php /* End sample webform confirmation page */ ?>
69
  ```
71 70

  
72 71
- You may edit the webform-confirmation.tpl.php file in your theme directory,
73 72
  this will affect all the webform mails sent by your entire site. Or, if you
......
77 76

  
78 77
- Visit admin/settings/performance and click the "Clear cached data" button.
79 78

  
80
Theme display of an entire webform
81
----------------------------------
79
## Theme display of an entire webform
82 80

  
83 81
Theming a webform can be useful for rearranging elements or customizing the
84 82
appearance of multiple components at once. This tutorial assumes usage
......
100 98
  you have good reason to do so (like you're forwarding your webform to a custom
101 99
  PHP or PERL script).
102 100

  
103
Theme display of a webform submission display
104
---------------------------------------------
101
## Theme display of a webform submission display
105 102

  
106 103
Theming the display of a webform submission works the same way as theming a
107 104
webform form. Webform uses Drupal "renderable" style arrays for the display of
drupal7/sites/all/modules/webform/components/date.inc
407 407
 * Element validation for Webform date fields.
408 408
 */
409 409
function webform_validate_date($element, $form_state) {
410
  $field_types = array('day', 'month', 'year');
410
  $date_parts = array('day', 'month', 'year');
411 411

  
412 412
  // Determine if the user has specified a date. Hidden parts of the date will
413 413
  // be submitted automatically.
414
  foreach ($field_types as $field_type) {
415
    if (!in_array($field_type, $element['#exclude']) && $element[$field_type]['#value'] !== '') {
414
  foreach ($date_parts as $date_part) {
415
    if (!in_array($date_part, $element['#exclude']) && $element[$date_part]['#value'] !== '') {
416 416
      $field_found = TRUE;
417 417
    }
418 418
  }
419 419

  
420 420
  if (isset($field_found)) {
421 421
    // Check that each part of the date has been filled in.
422
    foreach ($field_types as $field_type) {
423
      if (empty($element[$field_type]['#value'])) {
424
        form_error($element[$field_type], t('!part in !name is missing.', array('!name' => $element['#title'], '!part' => $element[$field_type]['#title'])));
422
    foreach ($date_parts as $date_part) {
423
      if (empty($element[$date_part]['#value'])) {
424
        form_error($element[$date_part], t('!part in !name is missing.', array('!name' => $element['#title'], '!part' => $element[$date_part]['#title'])));
425 425
        $missing_fields = TRUE;
426 426
      }
427 427
    }
......
430 430
    }
431 431

  
432 432
    // Ensure date is made up of integers.
433
    foreach (array('year', 'month', 'day') as $date_part) {
433
    foreach ($date_parts as $date_part) {
434 434
      $element[$date_part]['#value'] = (int) $element[$date_part]['#value'];
435 435
    }
436 436

  
drupal7/sites/all/modules/webform/components/email.inc
61 61
    '#size' => 60,
62 62
    '#maxlength' => 127,
63 63
    '#weight' => 0,
64
    '#attributes' => ($component['value'] == '[current-user:mail]' && count(form_get_errors()) == 0) ? array('disabled' => TRUE) : array(),
64
    '#attributes' => ($component['value'] == '[current-user:mail]' && !form_get_errors()) ? array('disabled' => TRUE) : array(),
65 65
    '#id' => 'email-value',
66 66
  );
67 67
  $form['user_email'] = array(
drupal7/sites/all/modules/webform/css/webform.css
34 34
.webform-container-inline.webform-component-textarea .form-textarea-wrapper {
35 35
  display: inline-block;
36 36
}
37

  
38
/* Reset so that these appear the same as the label elements they replace. */
39
fieldset.fieldset-invisible,
40
fieldset.fieldset-invisible > legend {
41
  margin: 0;
42
  padding: 0;
43
  border: none;
44
  border-radius: 0;
45
  background: inherit;
46
  position: static;
47
  color: inherit;
48
  height: auto;
49
  width: auto;
50
  font-family: inherit;
51
  text-indent: 0;
52
  line-height: inherit;
53
  text-shadow: unset;
54
  top: 0;
55
  right: 0;
56
  bottom: 0;
57
  left: 0;
58
}
59
fieldset.fieldset-invisible > legend {
60
  font-weight: bold;
61
  font-size: 0.929em;
62
}
63
/* This margin causes the fieldset to be too big. */
64
fieldset.fieldset-invisible > div > div.form-item:last-child,
65
fieldset.fieldset-invisible > table {
66
  margin-bottom: 0;
67
}
68

  
37 69
.webform-component-textarea .grippie {
38 70
  display: block;
39 71
}
drupal7/sites/all/modules/webform/includes/webform.admin.inc
20 20
  );
21 21

  
22 22
  // Add each component to the form:
23
  $form['components'] = array('#tree' => TRUE);
23
  $form['components'] += array('#tree' => TRUE);
24 24
  $component_types = webform_components(TRUE);
25 25
  foreach ($component_types as $key => $component) {
26 26
    $form['components'][$key] = array(
......
255 255
    '#description' => t('When mapping emails addresses to a select component, limit the choice to components with less than the amount of options indicated. This is to avoid flooding the email settings form.'),
256 256
  );
257 257

  
258
  $form['advanced']['webform_fieldset_wrap'] = array(
259
    '#type' => 'checkbox',
260
    '#title' => t('Use fieldsets for grouped components'),
261
    '#default_value' => webform_variable_get('webform_fieldset_wrap'),
262
    '#description' => t('Components containing multiple fields, such as checkboxes and radio buttons, will be wrapped in fieldsets. This improves the accessibility of webforms and helps them conform to web standards, but may require updates to the CSS of the active theme.'),
263
  );
264

  
258 265
  $form = system_settings_form($form);
259 266
  $form['#theme'] = 'webform_admin_settings';
260 267
  array_unshift($form['#submit'], 'webform_admin_settings_submit');
drupal7/sites/all/modules/webform/includes/webform.components.inc
634 634
 * Field name validation for the webform unique key. Must be alphanumeric.
635 635
 */
636 636
function webform_component_edit_form_validate($form, &$form_state) {
637
  $node = $form['#node'];;
637
  $node = $form['#node'];
638 638

  
639 639
  if (!preg_match('/^[a-z0-9_]+$/i', $form_state['values']['form_key'])) {
640 640
    form_set_error('form_key', t('The form key %form_key is invalid. Please include only lowercase alphanumeric characters and underscores.', array('%form_key' => $form_state['values']['form_key'])));
drupal7/sites/all/modules/webform/includes/webform.conditionals.inc
1341 1341
 * Insert a conditional rule group into the database.
1342 1342
 */
1343 1343
function webform_conditional_insert($conditional) {
1344
  $transaction = db_transaction();
1344 1345
  drupal_write_record('webform_conditional', $conditional);
1345 1346
  foreach ($conditional['rules'] as $rid => $rule) {
1346 1347
    $rule['nid'] = $conditional['nid'];
......
1360 1361
 * Update a conditional setting in the database.
1361 1362
 */
1362 1363
function webform_conditional_update($node, $conditional) {
1364
  $transaction = db_transaction();
1363 1365
  webform_conditional_delete($node, $conditional);
1364 1366
  webform_conditional_insert($conditional);
1365 1367
}
......
1368 1370
 * Delete a conditional rule group.
1369 1371
 */
1370 1372
function webform_conditional_delete($node, $conditional) {
1373
  $transaction = db_transaction();
1371 1374
  db_delete('webform_conditional')
1372 1375
    ->condition('nid', $node->nid)
1373 1376
    ->condition('rgid', $conditional['rgid'])
drupal7/sites/all/modules/webform/includes/webform.report.inc
909 909
/**
910 910
 * Generate a Excel-readable CSV file containing all submissions for a Webform.
911 911
 *
912
 * Note that this function is generally no longer utilized. Instead Batch API
913
 * should be used to generate a file over multiple requests.
914
 *
915
 * @see webform_results_export_batch()
916
 *
917
 * @deprecated This function is schedule to be removed in webform 7.x-5.x. Use
918
 * the batch opertions instead.
912
 * @deprecated in webform:7.x-4.8 and is removed from webform:7.x-5.0. Use
913
 * webform_results_export_batch().
914
 * @see https://www.drupal.org/project/webform/issues/2465291
919 915
 *
920 916
 * @return array|null
921 917
 *   The array of export info or null if the file could not be opened.
......
1075 1071
/**
1076 1072
 * Returns rows of downloadable webform data.
1077 1073
 *
1074
 * @deprecated in webform:7.x-4.8 and is removed from webform:7.x-5.0. See
1075
 * webform_results_download_rows_process().
1076
 * @see https://www.drupal.org/project/webform/issues/2465291
1077
 *
1078 1078
 * @param $node
1079 1079
 *   The webform node on which to generate the analysis.
1080 1080
 * @param array $options
......
1089 1089
 *   An array of rows built according to the provided $serial_start and
1090 1090
 *   $pager_count variables. Note that the current page number is determined
1091 1091
 *   by the super-global $_GET['page'] variable.
1092
 *
1093
 * @deprecated This function is scheduled to be removed in webform 7.x-5.x.
1094 1092
 */
1095 1093
function webform_results_download_rows($node, array $options, $serial_start = 0, &$last_sid = NULL) {
1096 1094
  // Get all the required submissions for the download.
......
1882 1880
/**
1883 1881
 * Given a set of range options, retrieve a set of SIDs for a webform node.
1884 1882
 *
1885
 * @deprecated This function is scheduled to be removed int webform 7.x-5.x.
1886
 * Use webform_download_sids_query() instead.
1883
 * @deprecated in webform:7.x-4.8 and is removed from webform:7.x-5.0. Use
1884
 * webform_download_sids_query().
1885
 * @see https://www.drupal.org/project/webform/issues/2465291
1887 1886
 */
1888 1887
function webform_download_sids($nid, $range_options, $uid = NULL) {
1889 1888
  return webform_download_sids_query($nid, $range_options, $uid)
drupal7/sites/all/modules/webform/includes/webform.submissions.inc
95 95
 *   The existing submission SID.
96 96
 */
97 97
function webform_submission_update($node, $submission) {
98
  $transaction = db_transaction();
98 99
  // Allow other modules to modify the submission before saving.
99 100
  foreach (module_implements('webform_submission_presave') as $module) {
100 101
    $function = $module . '_webform_submission_presave';
......
145 146
 *   The new submission SID.
146 147
 */
147 148
function webform_submission_insert($node, $submission) {
149
  $transaction = db_transaction();
148 150
  // The submission ID may already be set if being called as an update.
149 151
  if (!isset($submission->sid) && (!isset($submission->is_new) || $submission->is_new == FALSE)) {
150 152
    // Allow other modules to modify the submission before saving.
......
191 193
 *   The webform submission object to be deleted from the database.
192 194
 */
193 195
function webform_submission_delete($node, $submission) {
196
  $transaction = db_transaction();
194 197
  // Iterate through all components and let each do cleanup if necessary.
195 198
  foreach ($node->webform['components'] as $cid => $component) {
196 199
    if (isset($submission->data[$cid])) {
......
507 510

  
508 511
  // Determine the mode in which we're displaying this submission.
509 512
  $mode = ($format != 'form') ? 'display' : 'form';
510
  if (strpos(request_uri(), 'print/') !== FALSE) {
513
  if (strpos(request_path(), 'print/') !== FALSE) {
511 514
    $mode = 'print';
512 515
  }
513
  if (strpos(request_uri(), 'printpdf/') !== FALSE) {
516
  if (strpos(request_path(), 'printpdf/') !== FALSE) {
514 517
    $mode = 'pdf';
515 518
  }
516 519

  
......
663 666
}
664 667

  
665 668
/**
666
 * Print a Webform submission for display on a page or in an e-mail.
669
 * Prepare a Webform submission for display on a page or in an e-mail.
670
 *
671
 * @param object $node
672
 *   The node object.
673
 * @param object $submission
674
 *   The submission object.
675
 * @param array $email
676
 *   The email configuration array.
677
 * @param string $format
678
 *   The format the form should be displayed as. May be one of the following:
679
 *   - form: Show as an editable form.
680
 *   - html: Show as HTML results.
681
 *   - text: Show as plain text.
682
 * @param array $excluded_components
683
 *   An array of components to exclude as cid.
684
 *
685
 * @return array
686
 *   A renderable array of the submission.
667 687
 */
668 688
function webform_submission_render($node, $submission, $email, $format, $excluded_components = NULL) {
669 689
  $component_tree = array();
......
948 968
    if ($uid === 0) {
949 969
      $submissions = isset($_SESSION['webform_submission']) ? $_SESSION['webform_submission'] : NULL;
950 970
      if ($submissions) {
951
        $query->condition('ws.sid', $submissions, 'IN');
971
        $query->condition('ws.sid', array_keys($submissions), 'IN');
952 972
      }
953 973
      else {
954 974
        // Intentionally never match anything if the anonymous user has no
drupal7/sites/all/modules/webform/js/webform.js
84 84

  
85 85
      // Prevent the calendar button from submitting the form.
86 86
      $calendar.click(function (event) {
87
        $(this).focus();
88
        event.preventDefault();
87
        // This event is triggered also when pressing enter when the focus is on
88
        // previous webform components, but we only want to do something when
89
        // we are on the calendar component. By checking the event client x/y
90
        // position we known if it was the user clicking. For keyboard navigators
91
        // simply the focus handles the date picker so we don't have to do
92
        // anything special for them.
93
        if (event.clientX !== 0 && event.clientY !== 0) {
94
          // Focus is only necessary for Safari. But it has no impact on other
95
          // browsers.
96
          $(this).focus();
97
          event.preventDefault();
98
        }
99
      });
100

  
101
      // Clear date on backspace or delete.
102
      $calendar.keyup(function (e) {
103
        if (e.keyCode == 8 || e.keyCode == 46) {
104
          $.datepicker._clearDate(this);
105
        }
89 106
      });
90 107
    });
91 108
  };
......
112 129
   */
113 130
  Drupal.webform.conditionalCheck = function (e) {
114 131
    var $triggerElement = $(e.target).closest('.webform-component');
132
    if (!$triggerElement.length) {
133
      return;
134
    }
115 135
    var $form = $triggerElement.closest('form');
116 136
    var triggerElementKey = $triggerElement.attr('class').match(/webform-component--[^ ]+/)[0];
117 137
    var settings = e.data.settings;
......
238 258
          case 'require':
239 259
            var $requiredSpan = $target.find('.form-required, .form-optional').first();
240 260
            if (actionResult != $requiredSpan.hasClass('form-required')) {
241
              var $targetInputElements = $target.find("input:text,textarea,input[type='email'],select,input:radio,input:file");
261
              var $targetInputElements = $target.find("input:text,textarea,input[type='email'],select,input:radio,input:checkbox,input:file");
242 262
              // Rather than hide the required tag, remove it so that other
243 263
              // jQuery can respond via Drupal behaviors.
244 264
              Drupal.detachBehaviors($requiredSpan);
drupal7/sites/all/modules/webform/templates/webform-mail.tpl.php
29 29
<?php print ($email['html'] ? '<p>' : '') . t('Submitted by anonymous user: [submission:ip-address]') . ($email['html'] ? '</p>' : ''); ?>
30 30
<?php endif; ?>
31 31

  
32
<?php print ($email['html'] ? '<p>' : '') . t('Submitted values are') . ':' . ($email['html'] ? '</p>' : ''); ?>
32
<?php print ($email['html'] ? '<p>' : '') . t('Submitted values are:') . ($email['html'] ? '</p>' : ''); ?>
33 33

  
34 34
[submission:values]
35 35

  
drupal7/sites/all/modules/webform/tests/WebformSubmissionTestCase.test
23 23
    $this->drupalLogin($this->webform_users['admin']);
24 24
    $this->webformReset();
25 25
    $this->webformSubmissionExecute('sample');
26

  
27
    $loggedInUser = $this->loggedInUser;
28

  
26 29
    $this->drupalLogout();
30

  
31
    // Test webform_get_submission_count().
32
    $this->webformSubmissionExecute('sample');
33

  
34
    $count = webform_get_submission_count($this->webformForm()->nid);
35
    $this->assertIdentical((int) $count, 2, 'webform_get_submission_count() counts 2 total submissions.');
36

  
37
    $count = webform_get_submission_count($this->webformForm()->nid, $loggedInUser->uid);
38
    $this->assertIdentical((int) $count, 1, 'webform_get_submission_count() counts 1 submission from loggedInUser.');
39

  
40
    // Counting the anonymous submission doesn't work because
41
    // $_SESSION['webform_submission'] is not populated in testing.
27 42
  }
28 43

  
29 44
  /**
......
156 171
      $actual_value = $actual_submission->data[$cid];
157 172
      $result = $this->assertEqual($stable_value, $actual_value, t('Component @form_key data integrity check when using @type values.', array('@form_key' => $component['form_key'], '@type' => $value_type)), t('Webform'));
158 173
      if (!$result || $result === 'fail') {
159
        $this->fail(t('Expected !expected', array('!expected' => print_r($stable_value, TRUE))) . "\n\n" . t('Recieved !recieved', array('!recieved' => print_r($actual_value, TRUE))), t('Webform'));
174
        $this->fail(t("Expected !expected\n\nRecieved !recieved", array('!expected' => print_r($stable_value, TRUE), '!recieved' => print_r($actual_value, TRUE))), t('Webform'));
160 175
      }
161 176
    }
162 177
  }
drupal7/sites/all/modules/webform/tests/WebformTestCase.test
12 12
   * {@inheritdoc}
13 13
   */
14 14
  public function setUp($added_modules = array()) {
15
    // Enable Webform and Token module if available.
16
    if (module_exists('token')) {
17
      $modules = array('webform', 'token');
18
    }
19
    else {
20
      $modules = array('webform');
21
    }
15
    // Enable Webform and Token modules.
16
    $modules = array('webform', 'token');
22 17
    parent::setUp(array_merge($modules, $added_modules));
23 18

  
24 19
    // Create a profile field to test [user:?] tokens.
......
724 719
          'pid' => '0',
725 720
          'weight' => '-15',
726 721
        ),
727
        // Manually hard-code the input if token is not available.
728
        // @todo: Update after http://drupal.org/node/1347790 is finished.
729
        'sample values' => module_exists('token') ? NULL : 'bar',
722
        'sample values' => NULL,
730 723
        'database values' => array('bar'),
731
        'database default values' => module_exists('token') ? array('bar') : array(''),
724
        'database default values' => array('bar'),
732 725
      ),
733 726
      'textfield_profile' => array(
734 727
        'component' => array(
......
745 738
        ),
746 739
        'sample values' => 'Female',
747 740
        'database values' => array('Female'),
748
        // The default value will be blank if token does not exist.
749
        // @todo: Update after http://drupal.org/node/1347790 is finished.
750
        'database default values' => module_exists('token') ? array($this->webform_users['admin']->gender[LANGUAGE_NONE][0]['value']) : array(''),
741
        'database default values' => array($this->webform_users['admin']->gender[LANGUAGE_NONE][0]['value']),
751 742
      ),
752 743

  
753 744
      // Test time components.
drupal7/sites/all/modules/webform/tests/WebformUnitTestCase.test
1
<?php
2

  
3
/**
4
 * Webform module unit tests.
5
 */
6
class WebformUnitTestCase extends DrupalUnitTestCase {
7

  
8
  /**
9
   * {@inheritdoc}
10
   */
11
  public static function getInfo() {
12
    return array(
13
      'name' => t('Webform unit tests'),
14
      'description' => t('Unit tests for Webform functions.'),
15
      'group' => t('Webform'),
16
    );
17
  }
18

  
19
  /**
20
   * The tests.
21
   */
22
  public function test() {
23
    require_once __DIR__ . '/../webform.module';
24

  
25
    $test = webform_format_email_address('test@example.com', 'John Smith');
26
    $sample = '"John Smith" <test@example.com>';
27
    $this->assertIdentical($test, $sample, 'webform_format_email_address() returns string for single name and email address.');
28

  
29
    $test = webform_format_email_address('default', 'default');
30
    $sample = '"' . webform_variable_get('webform_default_from_name') . '" <' . webform_variable_get('webform_default_from_address') . '>';
31
    $this->assertIdentical($test, $sample, 'webform_format_email_address() handles defaults.');
32

  
33
    $test = webform_format_email_address('test@example.com', NULL);
34
    $sample = 'test@example.com';
35
    $this->assertIdentical($test, $sample, 'webform_format_email_address() handles NULL name.');
36

  
37
    $test = webform_format_email_address('test@example.com', 'John Smith', NULL, NULL, TRUE, FALSE);
38
    $sample = ['"John Smith" <test@example.com>'];
39
    $this->assertIdentical($test, $sample, 'webform_format_email_address() returns array for single name and email address.');
40

  
41
    $test = webform_format_email_address(['test1@example.com', 'test2@example.com'], 'John Smith');
42
    $sample = '"John Smith" <test1@example.com>';
43
    $this->assertIdentical($test, $sample, 'webform_format_email_address() returns single string for multiple email addresses by default.');
44

  
45
    $test = webform_format_email_address(['test1@example.com', 'test2@example.com'], ['John One', 'John Two'], NULL, NULL, TRUE, FALSE);
46
    $sample = ['"John One" <test1@example.com>', '"John Two" <test2@example.com>'];
47
    $this->assertIdentical($test, $sample, 'webform_format_email_address() returns array for multiple email addresses when $single is FALSE.');
48

  
49
    $test = webform_format_email_address(['test1@example.com', 'test2@example.com'], 'John One', NULL, NULL, TRUE, FALSE);
50
    $sample = ['"John One" <test1@example.com>', '"John One" <test2@example.com>'];
51
    $this->assertIdentical($test, $sample, 'webform_format_email_address() repeats first name when more emails than names provided.');
52

  
53
    $test = webform_format_email_address('test1@example.com, test2@example.com', 'John One', NULL, NULL, TRUE, FALSE);
54
    $sample = ['"John One" <test1@example.com>', '"John One" <test2@example.com>'];
55
    $this->assertIdentical($test, $sample, 'webform_format_email_address() accepts multiple emails as comma-separated string.');
56

  
57
    $node = (object) [
58
      'webform' => [
59
        'components' => [
60
          1 => ['name' => 'Email component', 'type' => 'textfield'],
61
          2 => ['name' => 'Name component', 'type' => 'textfield'],
62
        ],
63
      ],
64
    ];
65
    $test = webform_format_email_address(1, 2, $node);
66
    $sample = '"Value of Name component" <Value of "Email component">';
67
    $this->assertIdentical($test, $sample, 'webform_format_email_address() takes name and email from component names.');
68

  
69
    $submission = (object) [
70
      'data' => [
71
        1 => ['test@example.com'],
72
        2 => ['John Smith'],
73
      ],
74
    ];
75
    $test = webform_format_email_address(1, 2, $node, $submission);
76
    $sample = '"John Smith" <test@example.com>';
77
    $this->assertIdentical($test, $sample, 'webform_format_email_address() takes name and email from submission values.');
78
  }
79

  
80
}
drupal7/sites/all/modules/webform/views/webform_handler_relationship_submission_data.inc
59 59
    parent::options_submit($form, $form_state);
60 60
    _webform_views_options_submit($form, $form_state);
61 61
    $options =& $form_state['values']['options'];
62
    $options['webform_form_key'] = $options['webform_join_by_form_key'] == 'form_key' && ($node = node_load($options['webform_nid']))
62
    $options['webform_form_key'] = $options['webform_join_by'] == 'form_key' && ($node = node_load($options['webform_nid']))
63 63
                                        ? $node->webform['components'][$options['webform_cid']]['form_key']
64 64
                                        : NULL;
65 65
    // Drop PHP reference.
drupal7/sites/all/modules/webform/webform.api.php
238 238
 * presented when the webform is displayed to that user. To allow multiple
239 239
 * drafts, implement this alter function to set the $sid to NULL, or use your
240 240
 * application's business logic to determine whether a new draft or which of
241
 * he pre-existing drafts should be presented.
241
 * the pre-existing drafts should be presented.
242 242
 *
243 243
 * @param int $sid
244 244
 *   The id of the most recent submission to be presented for editing. Change
drupal7/sites/all/modules/webform/webform.info
38 38
files[] = tests/WebformPermissionsTestCase.test
39 39
files[] = tests/WebformSubmissionTestCase.test
40 40
files[] = tests/WebformTestCase.test
41
files[] = tests/WebformUnitTestCase.test
41 42

  
42
; Information added by Drupal.org packaging script on 2019-01-07
43
version = "7.x-4.19"
43
; Information added by Drupal.org packaging script on 2019-08-09
44
version = "7.x-4.20"
44 45
core = "7.x"
45 46
project = "webform"
46
datestamp = "1546876989"
47
datestamp = "1565386991"
drupal7/sites/all/modules/webform/webform.install
645 645
    'indexes' => array(
646 646
      'nid' => array('nid'),
647 647
      'sid_nid' => array('sid', 'nid'),
648
      // For all but MS SQL Server databases, 64-character index is created on the data column after the schema is installed.
648
      // For all but MS SQL Server databases, 64-character index is created on
649
      // the data column after the schema is installed.
649 650
    ),
650 651
  );
651 652

  
......
796 797
  variable_del('webform_default_format');
797 798
  variable_del('webform_format_override');
798 799
  variable_del('webform_email_select_max');
800
  variable_del('webform_fieldset_wrap');
799 801
  variable_del('webform_node_types_primary');
800 802
  variable_del('webform_date_type');
801 803
  variable_del('webform_export_format');
......
1972 1974
  }
1973 1975

  
1974 1976
  // Begin a transaction for updating the serial numbers. The transaction will
1975
  // commit when $txn is unset or goesout-of-scope.
1976
  $txn = db_transaction();
1977
  // commit when $transaction is unset or goes out-of-scope.
1978
  $transaction = db_transaction();
1977 1979

  
1978 1980
  // Delete stray entries from the Webform tables before adding serial numbers.
1979 1981
  db_query("DELETE FROM {webform_submissions} WHERE nid NOT IN (SELECT nid FROM {webform})");
......
2009 2011
      ->execute();
2010 2012
  }
2011 2013
  // Commit the transaction.
2012
  unset($txn);
2014
  unset($transaction);
2013 2015

  
2014 2016
  // Now that every submission has a serial number, make serial numbers required.
2015 2017
  $spec['not null'] = TRUE;
......
2060 2062
 * causes no problem, this update removes the schema module's warning.
2061 2063
 */
2062 2064
function webform_update_7418() {
2063
  // While there should never be any NULL values in the extra field, change them to '' to be safe.
2065
  // While there should never be any NULL values in the extra field, change them
2066
  // to '' to be safe.
2064 2067
  db_update('webform_emails')
2065 2068
    ->fields(array('extra' => ''))
2066 2069
    ->isNull('extra')
2067 2070
    ->execute();
2068
  // Pass a complete field specification to db_change_field for cross-database compatiblity.
2071
  // Pass a complete field specification to db_change_field for cross-database
2072
  // compatiblity.
2069 2073
  $spec = array(
2070 2074
    'description' => 'A serialized array of additional options for the e-mail configuration, including excluded components and value mapping for the TO and FROM addresses for select lists.',
2071 2075
    'type' => 'text',
......
2118 2122
}
2119 2123

  
2120 2124
/**
2121
 * Convert conditionals to be able to support multiple actions per conditional. Backup your database before proceeding. WARNING: Sites with many, many conditionals should execute this update via drush to avoid a PHP timeout.
2125
 * Convert conditionals to be able to support multiple actions per conditional.
2126
 *
2127
 * Backup your database before proceeding. WARNING: Sites with many, many
2128
 * conditionals should execute this update via drush to avoid a PHP timeout.
2122 2129
 */
2123 2130
function webform_update_7423() {
2124 2131
  // Create webform_condtional_actions table.
......
2183 2190
    db_create_table('webform_conditional_actions', $schema['webform_conditional_actions']);
2184 2191
  }
2185 2192

  
2186
  // In a site with many, many conditionals, the db_insert may timeout. Start a transaction to ensure atomic action.
2187
  $tx = db_transaction();
2188
  // Copy target information from existing webform_conditional table to new webfrom_condtional_actions table.
2193
  // In a site with many, many conditionals, the db_insert may timeout. Start a
2194
  // transaction to ensure atomic action.
2195
  $transaction = db_transaction();
2196
  // Copy target information from existing webform_conditional table to new
2197
  // webfrom_condtional_actions table.
2189 2198
  $select = db_select('webform_conditional', 'c')
2190 2199
    ->fields('c', array('nid', 'rgid', 'action', 'target_type', 'target'))
2191 2200
    ->orderBy('nid')->orderBy('rgid');
......
2195 2204
    ->execute();
2196 2205

  
2197 2206
  // Commit the insert.
2198
  unset($tx);
2207
  unset($transaction);
2199 2208

  
2200 2209
  // Remove unneeded columns from webform_conditional.
2201 2210
  foreach (array('action', 'target_type', 'target') as $fieldname) {
......
2204 2213
    }
2205 2214
  }
2206 2215

  
2207
  // Rebuild the registry because this point release contains a new class: WebformConditionals.
2216
  // Rebuild the registry because this point release contains a new class:
2217
  // WebformConditionals.
2208 2218
  registry_rebuild();
2209 2219

  
2210 2220
  return t('Webform database tables were successfully adjusted to allow more than one action for each conditional.');
......
2254 2264
}
2255 2265

  
2256 2266
/**
2257
 * Add database columns for submission completed and modified timestamps. Sites with many submissions may wish to use drush to execute this update.
2267
 * Add database columns for submission completed and modified timestamps.
2268
 *
2269
 * Sites with many submissions may wish to use drush to execute this update.
2258 2270
 */
2259 2271
function webform_update_7427() {
2260 2272
  // Create new timestamp columns.
......
2278 2290
    }
2279 2291
  }
2280 2292

  
2281
  // In a site with many submissions, the db_update may timeout. Start a transaction to ensure atomic action.
2282
  $tx = db_transaction();
2293
  // In a site with many submissions, the db_update may timeout. Start a
2294
  // transaction to ensure atomic action.
2295
  $transaction = db_transaction();
2283 2296
  // Copy submitted to completed for non-draft submissions.
2284 2297
  db_update('webform_submissions')
2285 2298
    ->expression('completed', 'submitted')
2286 2299
    ->condition('is_draft', 0)
2287 2300
    ->execute();
2288 2301
  // Commit the update.
2289
  unset($tx);
2302
  unset($transaction);
2290 2303

  
2291 2304
  // Start another transaction.
2292
  $tx = db_transaction();
2305
  $transaction = db_transaction();
2293 2306
  db_update('webform_submissions')
2294 2307
    ->expression('modified', 'submitted')
2295 2308
    ->execute();
2296 2309
  // Commit the update.
2297
  unset($tx);
2310
  unset($transaction);
2298 2311

  
2299 2312
  // Clear the views cache since to see the completed and modified views fields.
2300 2313
  cache_clear_all('*', 'cache_views', TRUE);
......
2322 2335
}
2323 2336

  
2324 2337
/**
2325
 * Add a column to the submission table to store the page on which to resume a draft. Sites with many, many submissions may wish to execute this update with 'drush updatedb'.
2338
 * Add column highest_valid_page to webform_submissions table.
2339
 *
2340
 * Add a column to the submission table to store the page on which to resume a
2341
 * draft. Sites with many, many submissions may wish to execute this update with
2342
 * 'drush updatedb'.
2326 2343
 */
2327 2344
function webform_update_7429() {
2328 2345
  // Add highest_valid_page column to webform_submissions.
drupal7/sites/all/modules/webform/webform.module
2188 2188
    $message = t('Submissions for this form are closed.');
2189 2189
  }
2190 2190
  elseif ($node->webform['confidential'] && user_is_logged_in()) {
2191
    $message = t('This form is confidential. You must <a href="!url">Log out</a> to submit it.', array('!url' => url('/user/logout', array('query' => array('destination' => request_uri())))));
2191
    $message = t('This form is confidential. You must <a href="!url">Log out</a> to submit it.', array('!url' => url('user/logout', array('query' => drupal_get_destination()))));
2192 2192
  }
2193 2193
  // If open and not allowed to submit the form, give an explanation.
2194 2194
  elseif (array_search(TRUE, $allowed_roles) === FALSE && $user->uid != 1) {
......
3271 3271
  // Merge any stored submission data for multistep forms.
3272 3272
  $original_values = is_array($form_state['values']['submitted']) ? $form_state['values']['submitted'] : array();
3273 3273
  if (isset($form_state['storage']['submitted'])) {
3274
    // Array + operator keeps all elements of left operand and discards any duplicate elements in right operand.
3274
    // Array + operator keeps all elements of left operand and discards any
3275
    // duplicate elements in right operand.
3275 3276
    $original_values += $form_state['storage']['submitted'];
3276 3277
  }
3277 3278

  
......
3754 3755
    $variables['element']['#id'] = NULL;
3755 3756
  }
3756 3757

  
3758
  // Determine whether or not this element has form control children. If so and
3759
  // if webform_fieldset_wrap is TRUE, wrap them in a fieldset and use legend
3760
  // instead of label.
3761
  $has_element_children = FALSE;
3762
  if (webform_variable_get('webform_fieldset_wrap')) {
3763
    foreach (array_keys($element) as $key) {
3764
      if (substr($key, 0, 1) !== '#') {
3765
        $has_element_children = TRUE;
3766
        break;
3767
      }
3768
    }
3769
  }
3770

  
3771
  if ($has_element_children) {
3772
    $output .= '<fieldset class="fieldset-invisible">';
3773
  }
3774

  
3757 3775
  switch ($element['#title_display']) {
3758 3776
    case 'inline':
3759 3777
      $output .= $description[$above];
......
3761 3779
    case 'before':
3762 3780
    case 'invisible':
3763 3781
    case 'after':
3764
      $title = ' ' . theme('form_element_label', $variables);
3782
      if ($has_element_children) {
3783
        $title = '<legend>' . $element['#title'];
3784

  
3785
        if ($element['#required']) {
3786
          $title .= ' ' . theme('form_required_marker', $variables);
3787
        }
3788

  
3789
        $title .= '</legend>';
3790
      }
3791
      else {
3792
        $title = ' ' . theme('form_element_label', $variables);
3793
      }
3765 3794
      break;
3766 3795
  }
3767 3796

  
......
3788 3817
  $output .= "\n";
3789 3818

  
3790 3819
  $output .= $description[!$above];
3820

  
3821
  if ($has_element_children) {
3822
    $output .= '</fieldset>';
3823
  }
3824

  
3791 3825
  $output .= "</div>\n";
3792 3826

  
3793 3827
  return $output;
......
3997 4031
}
3998 4032

  
3999 4033
/**
4000
 * This function is deprecated! Use webform_replace_tokens() instead.
4034
 * Wrapper for webform_replace_tokens().
4001 4035
 *
4002
 * @deprecated
4036
 * @deprecated in webform:7.x-4.0 and is removed from webform:7.x-5.0. Use
4037
 * webform_replace_tokens().
4038
 * @see https://www.drupal.org/project/webform/issues/2038199
4003 4039
 */
4004 4040
function _webform_filter_values($string, $node = NULL, $submission = NULL, $email = NULL, $strict = TRUE) {
4005 4041
  $output = webform_replace_tokens($string, $node, $submission, $email, $strict);
......
4122 4158
    }
4123 4159
  }
4124 4160
  $parsed_redirect_url['fragment'] = webform_replace_tokens($parsed_redirect_url['fragment'], $node, $submission);
4125
  // Determine whether the path is internal or external. Paths which contain the site's
4126
  // base url are still considered internal. #webform_external is private to webform.
4161
  // Determine whether the path is internal or external. Paths which contain the
4162
  // site's base url are still considered internal. #webform_external is private
4163
  // to webform.
4127 4164
  $parsed_redirect_url['#webform_external'] = url_is_external($parsed_redirect_url['path']);
4128 4165
  foreach (array(NULL, TRUE, FALSE) as $https) {
4129 4166
    if (stripos($parsed_redirect_url['path'], url('', array('absolute' => TRUE, 'https' => $https))) === 0) {
......
4142 4179
}
4143 4180

  
4144 4181
/**
4145
 * Deprecated! Use webform_filter_descriptions() instead.
4182
 * Duplicates webform_filter_descriptions().
4146 4183
 *
4147
 * @deprecated
4184
 * @deprecated in webform:7.x-4.0 and is removed from webform:7.x-5.0. Use
4185
 * webform_filter_descriptions().
4186
 * @see https://www.drupal.org/project/webform/issues/2038199
4148 4187
 */
4149 4188
function _webform_filter_descriptions($string, $node = NULL, $submission = NULL) {
4150 4189
  return webform_filter_descriptions($string, $node, $submission);
......
4160 4199
}
4161 4200

  
4162 4201
/**
4163
 * Deprecated! Use webform_filter_xss() instead!
4202
 * Duplicates webform_filter_xss().
4164 4203
 *
4165
 * @deprecated
4204
 * @deprecated in webform:7.x-4.0 and is removed from webform:7.x-5.0. Use
4205
 * webform_filter_xss().
4206
 * @see https://www.drupal.org/project/webform/issues/2038199
4166 4207
 */
4167 4208
function _webform_filter_xss($string) {
4168 4209
  return webform_filter_xss($string);
......
4414 4455
    case 'webform_disabled_components':
4415 4456
      $result = variable_get('webform_disabled_components', array());
4416 4457
      break;
4458

  
4459
    case 'webform_fieldset_wrap':
4460
      $result = variable_get('webform_fieldset_wrap', FALSE);
4461
      break;
4417 4462
  }
4418 4463
  return $result;
4419 4464
}
......
4584 4629
  }
4585 4630

  
4586 4631
  foreach ($address as $key => $individual_address) {
4632
    $individual_address = trim($individual_address);
4587 4633
    $individual_address = webform_replace_tokens($individual_address, $node, $submission);
4588 4634
    $email_parts = webform_parse_email_address($individual_address);
4589 4635
    if ($format == 'long' && !empty($name[$key]) && !strlen($email_parts['name'])) {
......
4967 5013
  if ($submission) {
4968 5014
    $breadcrumb = menu_get_active_breadcrumb();
4969 5015

  
4970
    // Append the node title (or its menu name), in case it isn't in the path already.
5016
    // Append the node title (or its menu name), in case it isn't in the path
5017
    // already.
4971 5018
    $active_trail = menu_get_active_trail();
4972 5019
    $last_active = end($active_trail);
4973 5020
    $breadcrumb[] = $last_active['href'] === $node_path && !empty($last_active['in_active_trail'])
......
5120 5167

  
5121 5168
    // Date/Time formatting characters
5122 5169
    // WHAT           REQUIRED (at least 1) OPTIONAL (allowed but insufficient)
5123
    // ---------------------------------------------------------------------------
5170
    // -------------------------------------------------------------------------
5124 5171
    // Day-of-week                          DlNw
5125 5172
    // Day            dj                    Stz
5126 5173
    // Month          FmMn
5127 5174
    // Year           oYy                   L
5128 5175
    //
5129 5176
    //                NOT ALLOWED
5130
    // --------------------------------------------------------------------------
5177
    // -------------------------------------------------------------------------
5131 5178
    // Time           aABgGhHisueIOPTZ
5132 5179
    // Special        /.,-: <space>
5133 5180
    //
......
5303 5350
  // a transaction. The return value of db_transaction() must be assigned or the
5304 5351
  // transaction will commit immediately. The transaction will commit when $txn
5305 5352
  // goes out-of-scope.
5306
  $txn = db_transaction();
5353
  $transaction = db_transaction();
5307 5354

  
5308 5355
  // Get the next_serial value.
5309 5356
  $next_serial = db_select('webform', 'w')
......
5392 5439
    $form['#input_var_waring_parent'] = $parent_key;
5393 5440
  }
5394 5441
  if (!empty($form_state['input']) && array_key_exists($detect_key, $form_state['input']) && !array_key_exists('form_id', $form_state['input'])) {
5395
    // A form was submitted with POST, but the form_id was missing. The most likely cause of this
5396
    // is that the POST was truncated because PHP exceeded its max_input_vars limit.
5442
    // A form was submitted with POST, but the form_id was missing. The most
5443
    // likely cause of this is that the POST was truncated because PHP exceeded
5444
    // its max_input_vars limit.
5397 5445
    $subs = array(
5398 5446
      '@count' => webform_count_terminals($_POST),
5399 5447
      '@limit' => (int) ini_get('max_input_vars'),
......
5420 5468
  // Determine the limit on input vars for this server configuration.
5421 5469
  $limit = ini_get('max_input_vars');
5422 5470
  if ($limit) {
5423
    // Estimate the number of input vars needed to see if the PHP limit has been exceeded.
5424
    // Additional input_vars: op.
5471
    // Estimate the number of input vars needed to see if the PHP limit has been
5472
    // exceeded. Additional input_vars: op.
5425 5473
    $count = 1 + webform_count_input_vars($element);
5426 5474
    if ($count > $limit * 0.95) {
5427 5475
      $subs = array(

Also available in: Unified diff