Project

General

Profile

Revision 7b2d1845

Added by Assos Assos almost 4 years ago

Weekly update of contrib modules

View differences:

drupal7/sites/all/modules/file_entity/file_entity.admin.inc
1195 1195

  
1196 1196
/**
1197 1197
 * Element validate callback for the maximum upload size / file extension field.
1198
 * Only validates non-empty values.
1198 1199
 */
1199 1200
function file_entity_max_filesize_extensions_validate($element, &$form_state) {
1200 1201
  $list = explode("\n", $element['#value']);
......
1203 1204
    $matches = array();
1204 1205
    preg_match('/(.*)\|(.*)/', $text, $matches);
1205 1206

  
1206
    $extension = $matches[1];
1207
    $filesize = $matches[2];
1207
    if (isset($matches[1]) && isset($matches[2]) && !empty($matches[1]) && !empty($matches[2])) {
1208
      // Only validate non-empty values.
1209
      $extension = $matches[1];
1210
      $filesize = $matches[2];
1208 1211

  
1209
    //Validate filesize.
1210
    $element['#value'] = $filesize;
1211
    _file_generic_settings_max_filesize($element, $form_state);
1212
      //Validate filesize.
1213
      $element['#value'] = $filesize;
1214
      _file_generic_settings_max_filesize($element, $form_state);
1212 1215

  
1213
    //Validate extension.
1214
    $extensions = explode(' ', $form_state['input']['file_entity_default_allowed_extensions']);
1215
    if (!in_array($extension, $extensions)) {
1216
      form_error($element, t('"!extension" was not found in the list of allowed extensions.', array('!extension' => $extension)));
1216
      //Validate extension.
1217
      $extensions = explode(' ', $form_state['input']['file_entity_default_allowed_extensions']);
1218
      if (!in_array($extension, $extensions)) {
1219
        form_error($element, t('"!extension" was not found in the list of allowed extensions.', array('!extension' => $extension)));
1220
      }
1217 1221
    }
1218 1222
  }
1219 1223
}
drupal7/sites/all/modules/file_entity/file_entity.info
32 32
; We have to add a fake version so Git checkouts do not fail Media dependencies
33 33
version = 7.x-2.x-dev
34 34

  
35
; Information added by Drupal.org packaging script on 2020-06-01
36
version = "7.x-2.28"
35
; Information added by Drupal.org packaging script on 2020-06-05
36
version = "7.x-2.29"
37 37
core = "7.x"
38 38
project = "file_entity"
39
datestamp = "1591051455"
39
datestamp = "1591321853"
drupal7/sites/all/modules/file_entity/file_entity.module
1265 1265
 * @return string
1266 1266
 *   Returns the replaced title text.
1267 1267
 */
1268
function file_entity_replace_title($file, $replace_options = [], $title = NULL, $langcode = NULL) {
1269
  $replace_options += [
1268
function file_entity_replace_title($file, $replace_options = array(), $title = NULL, $langcode = NULL) {
1269
  $replace_options += array(
1270 1270
    'clear' => TRUE,
1271 1271
    'sanitize' => FALSE,
1272
  ];
1272
  );
1273 1273

  
1274 1274
  $title_default = '[file:field_file_image_title_text]';
1275 1275
  if (!isset($title)) {
......
1282 1282
    return $title_items ? $title_items[0]['value'] : '';
1283 1283
  }
1284 1284
  elseif (!empty($title)) {
1285
    $token_replaced = token_replace($title, ['file' => $file], $replace_options);
1285
    $token_replaced = token_replace($title, array('file' => $file), $replace_options);
1286 1286
    return decode_entities($token_replaced); // Filter out possible XSS.
1287 1287
  }
1288 1288

  
......
1304 1304
 * @return string
1305 1305
 *   Returns the replaced alt text.
1306 1306
 */
1307
function file_entity_replace_alt($file, $replace_options = [], $alt = NULL, $langcode = NULL) {
1308
  $replace_options += [
1307
function file_entity_replace_alt($file, $replace_options = array(), $alt = NULL, $langcode = NULL) {
1308
  $replace_options += array(
1309 1309
    'clear' => TRUE,
1310 1310
    'sanitize' => FALSE,
1311
  ];
1311
  );
1312 1312

  
1313 1313
  $alt_default = '[file:field_file_image_alt_text]';
1314 1314

  
......
1323 1323
    return $alt_items ? $alt_items[0]['value'] : '';
1324 1324
  }
1325 1325
  elseif (!empty($alt)) {
1326
    $token_replaced = token_replace($alt, ['file' => $file], $replace_options);
1326
    $token_replaced = token_replace($alt, array('file' => $file), $replace_options);
1327 1327
    return decode_entities($token_replaced); // Filter out possible XSS.
1328 1328
  }
1329 1329

  
drupal7/sites/all/modules/file_entity/file_entity.pages.inc
122 122
 * Generate form fields for the first step in the add file wizard.
123 123
 */
124 124
function file_entity_add_upload_step_upload($form, &$form_state, array $options = array()) {
125
  $upload_validators = file_entity_get_upload_validators($options);
125 126
  $form['upload'] = array(
126 127
    '#type' => 'managed_file',
127 128
    '#title' => t('Upload a new file'),
128 129
    '#upload_location' => file_entity_upload_destination_uri($options),
129
    '#upload_validators' => file_entity_get_upload_validators($options),
130
    '#upload_validators' => $upload_validators,
130 131
    '#progress_indicator' => 'bar',
131 132
    '#required' => TRUE,
132 133
    '#pre_render' => array('file_managed_file_pre_render', 'file_entity_upload_validators_pre_render'),
......
139 140
  $extensions = explode("\n", variable_get('file_entity_max_filesize_extensions'));
140 141

  
141 142
  if (!empty($extensions)) {
143
    $limits = array();
142 144

  
143
    $limits = '';
145
    // Limit extensions displayed to those in upload validator.
146
    $valid_extensions = array();
147
    if (!empty($upload_validators)) {
148
      foreach ($upload_validators['file_validate_extensions'] as $key => $values) {
149
        $valid_extensions[$key] = explode(' ', strtolower($values));
150
      }
151
    }
152
    // If there are valid extensions, merge sub-arrays into a single array.
153
    if (!empty($valid_extensions)) {
154
      $valid_extensions = call_user_func_array('array_merge', $valid_extensions);
155
    }
144 156

  
145 157
    foreach ($extensions as $position => $text) {
146 158
      $matches = array();
......
150 162
        $extension = $matches[1];
151 163
        $filesize = $matches[2];
152 164

  
153
        $limits .= $extension . ': ' . $filesize . ',';
165
        if (empty($valid_extensions) || in_array(strtolower($extension), $valid_extensions)) {
166
          $limits[] = trim($extension) . ': <strong>' . trim($filesize) . '</strong>';
167
        }
154 168
      }
155 169
    }
156 170

  
157
    $limits = rtrim($limits, ',');
158

  
159
    $form['upload']['#description'] = t('Files must be less than !size (!limits).', array('!size' => '<strong>' . format_size($form['upload']['#upload_validators']['file_entity_validate_size_extensions'][0]) . '</strong>', '!limits' => $limits));
160

  
171
    if (!empty($limits)) {
172
      // If less than or equal to 15 items to display, show as unordered list.
173
      // Otherwise, implode into a single list item.
174
      $list = array(
175
        '#theme' => 'item_list',
176
        '#list_type' => 'ul',
177
        '#items' => (count($limits) <= 15) ? $limits : array(implode(', ', $limits)),
178
      );
179

  
180
      if (!empty($valid_extensions)) {
181
        $form['upload']['#description'] = t('Files must be less than these sizes: !list',
182
          array(
183
            '!list' => render($list),
184
          )
185
        );
186
      }
187
      else {
188
        $form['upload']['#description'] = t('Files must be less than these sizes: !list The default maximum size is !size.',
189
          array(
190
            '!list' => render($list),
191
            '!size' => '<strong>' . format_size($form['upload']['#upload_validators']['file_entity_validate_size_extensions'][0]) . '</strong>'
192
          )
193
        );
194
      }
195
    }
161 196
  }
162 197

  
163 198
  $form['actions'] = array('#type' => 'actions');
......
357 392
        if (empty($label)) {
358 393
          $label = t('(entity label not loaded)');
359 394
        }
395
        $entity_label = $label;
360 396
        $entity_uri = empty($entities[$entity_id]) ? NULL : entity_uri($entity_type, $entities[$entity_id]);
361 397

  
362 398
        // Link the label to the URI when possible.
drupal7/sites/all/modules/file_entity/tests/file_entity_test.info
5 5
dependencies[] = file_entity
6 6
hidden = TRUE
7 7

  
8
; Information added by Drupal.org packaging script on 2020-06-01
9
version = "7.x-2.28"
8
; Information added by Drupal.org packaging script on 2020-06-05
9
version = "7.x-2.29"
10 10
core = "7.x"
11 11
project = "file_entity"
12
datestamp = "1591051455"
12
datestamp = "1591321853"
drupal7/sites/all/modules/webform/components/number.inc
188 188
    '#type' => 'textfield',
189 189
    '#title' => t('Minimum'),
190 190
    '#default_value' => $component['extra']['min'],
191
    '#description' => t('Minimum numeric value. For example, 0 would ensure positive numbers.'),
191
    '#description' => t('Minimum numeric value. For example, 0 would ensure non-negative numbers.'),
192 192
    '#size' => 5,
193 193
    '#maxlength' => 10,
194 194
    '#weight' => 2.1,
......
649 649
        }
650 650
      }
651 651
      elseif ($element['#max'] != '' && $numeric_value > $element['#max']) {
652
        form_error($element, t('!name field value must be less than @max.', array('!name' => $element['#title'], '@max' => $element['#max'])));
652
        form_error($element, t('!name field value must be less than or equal to @max.', array('!name' => $element['#title'], '@max' => $element['#max'])));
653 653
      }
654 654
      elseif ($element['#min'] != '' && $numeric_value < $element['#min']) {
655
        form_error($element, t('!name field value must be greater than @min.', array('!name' => $element['#title'], '@min' => $element['#min'])));
655
        form_error($element, t('!name field value must be greater than or equal to @min.', array('!name' => $element['#title'], '@min' => $element['#min'])));
656 656
      }
657 657

  
658 658
      // Integer test.
drupal7/sites/all/modules/webform/includes/exporters/webform_exporter.inc
68 68
    drupal_add_http_header('Cache-Control', 'max-age=0');
69 69
  }
70 70

  
71
  /**
72
   * Get full filename of the export file, including the extension.
73
   *
74
   * @param string $filename
75
   *   The base filename of the export file.
76
   *
77
   * @return string
78
   *   The full filename of the export file, including the extension.
79
   */
80
  public function get_filename($filename) {
81
    return $filename;
82
  }
83

  
71 84
  /**
72 85
   * Write the start of the export file.
73 86
   *
drupal7/sites/all/modules/webform/includes/exporters/webform_exporter_delimited.inc
45 45

  
46 46
    // Convert tabs.
47 47
    if ($this->delimiter == "\t") {
48
      $extension = 'tsv';
49 48
      $content_type = 'text/tab-separated-values';
50 49
    }
51 50
    else {
52
      $extension = 'csv';
53 51
      $content_type = 'text/csv';
54 52
    }
55 53

  
56 54
    drupal_add_http_header('Content-Type', $content_type);
57
    drupal_add_http_header('Content-Disposition', "attachment; filename=$filename.$extension");
55
    drupal_add_http_header('Content-Disposition', 'attachment; filename=' . $this->get_filename($filename));
56
  }
57

  
58
  /**
59
   * {@inheritdoc}
60
   */
61
  public function get_filename($filename) {
62
    $extension = ($this->delimiter === "\t") ? 'tsv' : 'csv';
63
    return $filename . '.' . $extension;
58 64
  }
59 65

  
60 66
}
drupal7/sites/all/modules/webform/includes/exporters/webform_exporter_excel_delimited.inc
52 52
   */
53 53
  public function set_headers($filename) {
54 54
    drupal_add_http_header('Content-Type', 'application/x-msexcel');
55
    drupal_add_http_header('Content-Disposition', "attachment; filename=$filename.xls");
55
    drupal_add_http_header('Content-Disposition', 'attachment; filename=' . $this->get_filename($filename));
56 56
    drupal_add_http_header('Pragma', 'public');
57 57
    drupal_add_http_header('Cache-Control', 'max-age=0');
58 58
  }
59 59

  
60
  /**
61
   * {@inheritdoc}
62
   */
63
  public function get_filename($filename) {
64
    return $filename . '.xls';
65
  }
66

  
60 67
}
drupal7/sites/all/modules/webform/includes/exporters/webform_exporter_excel_xlsx.inc
155 155
    $zip_filepath = drupal_realpath($zip_uri);
156 156
    $file_filepath = drupal_realpath($file_uri);
157 157
    $zip = new ZipArchive();
158
    if ($zip->open($zip_filepath, ZipArchive::CREATE) === TRUE) {
158
    if ($zip->open($zip_filepath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {
159 159
      // Create a bare-bones Office Open XML format directory structure. This is
160 160
      // based on the sample simple XLSX file at
161 161
      // http://blogs.msdn.com/b/chrisrae/archive/2011/08/18/creating-a-simple-xlsx-from-scratch-using-the-open-xml-sdk.aspx
......
191 191
   */
192 192
  public function set_headers($filename) {
193 193
    drupal_add_http_header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
194
    drupal_add_http_header('Content-Disposition', "attachment; filename=$filename.xlsx");
194
    drupal_add_http_header('Content-Disposition', 'attachment; filename=' . $this->get_filename($filename));
195 195
    drupal_add_http_header('Pragma', 'public');
196 196
    drupal_add_http_header('Cache-Control', 'max-age=0');
197 197
  }
198 198

  
199
  /**
200
   * {@inheritdoc}
201
   */
202
  public function get_filename($filename) {
203
    return $filename . '.xlsx';
204
  }
205

  
199 206
  /**
200 207
   * Return all the parts needed to assemble a bare-bones XLSX package.
201 208
   */
drupal7/sites/all/modules/webform/includes/webform.components.inc
461 461
        '#title' => t('Label display'),
462 462
        '#default_value' => !empty($component['extra']['title_display']) ? $component['extra']['title_display'] : 'before',
463 463
        '#options' => array('before' => t('Above')) +
464
                      $inline_option +
465
                      $internal_option +
466
                      array('none' => t('None')),
464
          $inline_option +
465
          $internal_option +
466
          array('none' => t('None')),
467 467
        '#description' => t("Determines the placement of the component's label."),
468 468
      );
469 469
    }
......
996 996
    'email_address' => FALSE,
997 997
    'email_name' => FALSE,
998 998
    'required' => TRUE,
999
    'stores_data' => TRUE,
999 1000
    'title' => TRUE,
1000 1001
    'title_display' => TRUE,
1001 1002
    'title_inline' => TRUE,
drupal7/sites/all/modules/webform/includes/webform.conditionals.inc
260 260
 */
261 261
function webform_conditionals_form_submit($form, &$form_state) {
262 262
  $node = $form['#node'];
263
  // Get a fresh copy of the node so that we are only saving these changes.
264
  // Otherwise, changes to the Webform on another tab will be overwritten.
265
  $node = node_load($node->nid, NULL, TRUE);
263 266

  
264 267
  // Remove the new conditional placeholder.
265 268
  unset($form_state['values']['conditionals']['new']);
drupal7/sites/all/modules/webform/includes/webform.pages.inc
533 533
 * to add properties if needed into the $form['#node'] object before save.
534 534
 */
535 535
function webform_configure_form_submit_save($form, &$form_state) {
536
  $transaction = db_transaction();
536 537
  node_save($form['#node']);
537 538
  drupal_set_message(t('The form settings have been updated.'));
538 539

  
drupal7/sites/all/modules/webform/includes/webform.report.inc
265 265
/**
266 266
 * Theme the results table displaying all the submissions for a particular node.
267 267
 *
268
 * @param $node
269
 *   The node whose results are being displayed.
270
 * @param $components
271
 *   An associative array of the components for this webform.
272
 * @param $submissions
273
 *   An array of all submissions for this webform.
274
 * @param $total_count
275
 *   The total number of submissions to this webform.
276
 * @param $pager_count
277
 *   The number of results to be shown per page.
268
 * @param array $variables
269
 *   An array with keys:
270
 *    - node: The node whose results are being displayed.
271
 *    - components: An associative array of the components for this webform.
272
 *    - submissions: An array of all submissions for this webform.
273
 *    - total_count: The total number of submissions to this webform.
274
 *    - pager_count: The number of results to be shown per page.
278 275
 *
279 276
 * @return string
280 277
 *   HTML string with result data.
281 278
 */
282
function theme_webform_results_table($variables) {
279
function theme_webform_results_table(array $variables) {
283 280
  drupal_add_library('webform', 'admin');
284 281

  
285 282
  $node = $variables['node'];
283
  $components = $variables['components'];
286 284
  $submissions = $variables['submissions'];
287 285
  $total_count = $variables['total_count'];
288 286
  $pager_count = $variables['pager_count'];
......
304 302
    $component_headers = array();
305 303

  
306 304
    // Generate a cell for each component.
307
    foreach ($node->webform['components'] as $component) {
305
    foreach ($components as $component) {
308 306
      $data = isset($submission->data[$component['cid']]) ? $submission->data[$component['cid']] : NULL;
309 307
      $submission_output = webform_component_invoke($component['type'], 'table', $component, $data);
310 308
      if ($submission_output !== NULL) {
......
738 736
  $element['#webform_download_info']['serial'] = $last_download ? $last_download['serial'] : NULL;
739 737
  $element['#webform_download_info']['requested'] = $last_download ? $last_download['requested'] : $node->created;
740 738
  $element['#webform_download_info']['total'] = webform_get_submission_count($node->nid, NULL, NULL);
741
  $element['#webform_download_info']['new'] = webform_download_sids_count($node->nid, array('range_type' => 'new'));
739
  $element['#webform_download_info']['new'] = webform_download_sids_count($node->nid, array('range_type' => 'new', 'completion_type' => 'finished'));
740
  if ($node->webform['allow_draft'] || $node->webform['auto_save']) {
741
    $element['#webform_download_info']['new_draft'] = webform_download_sids_count($node->nid, array('range_type' => 'new', 'completion_type' => 'draft'));
742
  }
742 743

  
743 744
  return $element;
744 745
}
......
760 761
  $format = webform_date_format('short');
761 762
  $requested_date = format_date($download_info['requested'], 'custom', $format);
762 763
  $element['range_type']['new']['#theme_wrappers'] = array('webform_inline_radio');
763
  $element['range_type']['new']['#title'] .= ' (' . t('@count new since @date', array('@count' => $download_info['new'], '@date' => $requested_date)) . ')';
764
  if (isset($download_info['new_draft'])) {
765
    $args = array(
766
      '@new_draft' => $download_info['new_draft'],
767
      '@new' => $download_info['new'],
768
      '@date' => $requested_date,
769
    );
770
    $element['range_type']['new']['#title'] .= ' (' . t('@new_draft new drafts, @new new finished since @date', $args) . ')';
771
    $total_count = $download_info['new_draft'] + $download_info['new'];
772
  }
773
  else {
774
    $args = array(
775
      '@count' => $download_info['new'],
776
      '@date' => $requested_date,
777
    );
778
    $element['range_type']['new']['#title'] .= ' (' . t('@count new since @date', $args) . ')';
779
    $total_count = $download_info['new'];
780
  }
764 781

  
765 782
  // Disable option if there are no new submissions.
766
  if ($download_info['new'] == 0) {
783
  if ($total_count == 0) {
767 784
    $element['range_type']['new']['#attributes']['disabled'] = 'disabled';
768 785
  }
769 786

  
......
1071 1088
/**
1072 1089
 * Returns rows of downloadable webform data.
1073 1090
 *
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 1091
 * @param $node
1079 1092
 *   The webform node on which to generate the analysis.
1080 1093
 * @param array $options
......
1089 1102
 *   An array of rows built according to the provided $serial_start and
1090 1103
 *   $pager_count variables. Note that the current page number is determined
1091 1104
 *   by the super-global $_GET['page'] variable.
1105
 *
1106
 * @deprecated in webform:7.x-4.8 and is removed from webform:7.x-5.0. See
1107
 * webform_results_download_rows_process().
1108
 * @see https://www.drupal.org/project/webform/issues/2465291
1092 1109
 */
1093 1110
function webform_results_download_rows($node, array $options, $serial_start = 0, &$last_sid = NULL) {
1094 1111
  // Get all the required submissions for the download.
......
1354 1371
 */
1355 1372
function webform_results_export_success($node, $export_info) {
1356 1373
  if (!in_array($export_info['options']['range']['range_type'], array('range', 'range_serial', 'range_date')) && !empty($export_info['last_sid'])) {
1357
    // Insert a new record or update an existing record.
1358
    db_merge('webform_last_download')
1359
      ->key(array(
1360
        'nid' => $node->nid,
1361
        'uid' => $GLOBALS['user']->uid,
1362
      ))
1363
      ->fields(array(
1364
        'sid' => $export_info['last_sid'],
1365
        'requested' => REQUEST_TIME,
1366
      ))
1367
      ->execute();
1374
    webform_update_webform_last_download($node, $GLOBALS['user']->uid, $export_info['last_sid'], REQUEST_TIME);
1368 1375
  }
1369 1376
}
1370 1377

  
1378
/**
1379
 * Insert or update a download record in table {webform_last_download}.
1380
 *
1381
 * @param object $node
1382
 *   The Webform node of the record to update.
1383
 * @param int $uid
1384
 *   The user ID of the record to update.
1385
 * @param int $sid
1386
 *   The last downloaded submission number.
1387
 * @param int $requested
1388
 *   Timestamp of last download request.
1389
 *
1390
 * @return int
1391
 *   MergeQuery::STATUS_INSERT or ::STATUS_UPDATE.
1392
 */
1393
function webform_update_webform_last_download(stdClass $node, $uid, $sid, $requested) {
1394
  return db_merge('webform_last_download')
1395
    ->key(array(
1396
      'nid' => $node->nid,
1397
      'uid' => $uid,
1398
    ))
1399
    ->fields(array(
1400
      'sid' => $sid,
1401
      'requested' => $requested,
1402
    ))
1403
    ->execute();
1404
}
1405

  
1371 1406
/**
1372 1407
 * Menu callback; Download an exported file.
1373 1408
 *
......
1831 1866
 */
1832 1867
function webform_analysis_components_form_submit($form, $form_state) {
1833 1868
  $node = $form['#node'];
1869
  // Get a fresh copy of the node so that we are only saving these changes.
1870
  // Otherwise, changes to the Webform on another tab will be overwritten.
1871
  $node = node_load($node->nid, NULL, TRUE);
1834 1872
  foreach ($form_state['values']['components'] as $cid => $enabled) {
1835 1873
    $node->webform['components'][$cid]['extra']['analysis'] = (bool) $enabled;
1836 1874
  }
......
1880 1918
/**
1881 1919
 * Given a set of range options, retrieve a set of SIDs for a webform node.
1882 1920
 *
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
1921
 * @param int $nid
1922
 *   The node id of the webform.
1923
 * @param array $range_options
1924
 *   Associate array of range options.
1925
 * @param int $uid
1926
 *   The user id of the user whose last download information should be used,
1927
 *   or the current user if NULL. This is unrelated to which user submitted
1928
 *   the submissions.
1929
 *
1930
 * @return array
1931
 *   An array of submission IDs.
1886 1932
 */
1887
function webform_download_sids($nid, $range_options, $uid = NULL) {
1933
function webform_download_sids($nid, array $range_options, $uid = NULL) {
1888 1934
  return webform_download_sids_query($nid, $range_options, $uid)
1889 1935
    ->fields('ws', array('sid'))
1890 1936
    ->execute()
......
1893 1939

  
1894 1940
/**
1895 1941
 * Retrieves a count the number of matching submissions.
1942
 *
1943
 * @return int
1944
 *   The number number of matching submissions.
1896 1945
 */
1897 1946
function webform_download_sids_count($nid, $range_options, $uid = NULL) {
1898
  return webform_download_sids_query($nid, $range_options, $uid)
1947
  return (int) webform_download_sids_query($nid, $range_options, $uid)
1899 1948
    ->countQuery()
1900 1949
    ->execute()
1901 1950
    ->fetchField();
......
1930 1979
      $query->orderBy('ws.sid', 'ASC');
1931 1980
      break;
1932 1981

  
1933
    case 'new':
1934
      // All Since Last Download.
1935
      $download_info = webform_download_last_download_info($nid, $uid);
1936
      $last_sid = $download_info ? $download_info['sid'] : 0;
1937
      $query
1938
        ->condition('ws.sid', $last_sid, '>')
1939
        ->orderBy('ws.sid', 'ASC');
1940
      break;
1941

  
1942 1982
    case 'latest':
1943 1983
      // Last x Submissions.
1944 1984
      $start_sid = webform_download_latest_start_sid($nid, $range_options['latest'], $range_options['completion_type']);
......
1963 2003
      $query->orderBy('ws.serial', 'ASC');
1964 2004
      break;
1965 2005

  
2006
    case 'new':
2007
      // All since last download. This is the same as 'range_date' except that
2008
      // the start date is the date of the last download.
2009
      $download_info = webform_download_last_download_info($nid, $uid);
2010
      $start_date = (int) $download_info ? $download_info['requested'] : 0;
2011
      $end_time = NULL;
2012
      // Fall through.
1966 2013
    case 'range_date':
1967
      $date_field = $range_options['completion_type'] == 'finished' ? 'ws.completed' : 'ws.submitted';
1968
      $format = webform_date_format('short');
1969
      $start_date = DateTime::createFromFormat($format, $range_options['start_date']);
1970
      $start_date->setTime(0, 0, 0);
1971
      $query->condition($date_field, $start_date->getTimestamp(), '>=');
1972
      $end_time = DateTime::createFromFormat($format, $range_options['end_date']);
1973
      if ($range_options['end_date'] != '' && ($end_time !== FALSE)) {
2014
      // If the submission is completed, use the completed date, otherwise, the
2015
      // submitted date.
2016
      $date_field = 'COALESCE(NULLIF(ws.completed, 0), ws.submitted)';
2017
      // This is required because SQLite uses dynamic typing.
2018
      if (db_driver() === 'sqlite') {
2019
        $date_field = 'CAST(' . $date_field . ' AS INTEGER)';
2020
      }
2021

  
2022
      if (!isset($start_date)) {
2023
        $format = webform_date_format('short');
2024
        $start_date = DateTime::createFromFormat($format, $range_options['start_date']);
2025
        $start_date->setTime(0, 0, 0);
2026
        $start_date = $start_date->getTimestamp();
2027

  
2028
        $end_time = DateTime::createFromFormat($format, $range_options['end_date']);
2029
      }
2030
      $query->where($date_field . ' >= :start_date', array(':start_date' => $start_date));
2031

  
2032
      if ($end_time) {
1974 2033
        // Check for the full day's submissions.
1975 2034
        $end_time->setTime(23, 59, 59);
1976
        $query->condition($date_field, $end_time->getTimestamp(), '<=');
2035
        $end_time = $end_time->getTimestamp();
2036
        $query->where($date_field . ' <= :end_time', array(':end_time' => $end_time));
1977 2037
      }
2038

  
1978 2039
      $query->orderBy($date_field, 'ASC');
1979 2040
      break;
1980 2041
  }
drupal7/sites/all/modules/webform/includes/webform.submissions.inc
13 13
/**
14 14
 * Given an array of submitted values, flatten it into data for a submission.
15 15
 *
16
 * @param $node
16
 * @param object $node
17 17
 *   The node object containing the current webform.
18
 * @param $submitted
18
 * @param array $submitted
19 19
 *   The submitted user values from the webform.
20 20
 *
21 21
 * @return array
22 22
 *   An array suitable for use in the 'data' property of a $submission object.
23 23
 */
24 24
function webform_submission_data($node, $submitted) {
25
  require_once __DIR__ . '/webform.components.inc';
26

  
25 27
  $data = array();
26 28

  
27 29
  foreach ($submitted as $cid => $values) {
28
    // Don't save pseudo-fields or pagebreaks as submitted data.
29
    if (!isset($node->webform['components'][$cid]) || $node->webform['components'][$cid]['type'] == 'pagebreak') {
30
    // Don't save pseudo-fields or components that do not collect data.
31
    if (!isset($node->webform['components'][$cid]) || !webform_component_feature($node->webform['components'][$cid]['type'], 'stores_data')) {
30 32
      continue;
31 33
    }
32 34

  
drupal7/sites/all/modules/webform/templates/webform-mail.tpl.php
21 21
 * different users when using the "default" e-mail template.
22 22
 */
23 23
?>
24
<?php print ($email['html'] ? '<p>' : '') . t('Submitted on [submission:date:long]') . ($email['html'] ? '</p>' : ''); ?>
24
<?php print ($email['html'] ? '<p>' : '') . t('Submitted on [submission:completed_date:long]') . ($email['html'] ? '</p>' : ''); ?>
25 25

  
26 26
<?php if ($user->uid): ?>
27 27
<?php print ($email['html'] ? '<p>' : '') . t('Submitted by user: [submission:user]') . ($email['html'] ? '</p>' : ''); ?>
drupal7/sites/all/modules/webform/tests/WebformSubmissionTestCase.test
29 29
    $this->drupalLogout();
30 30

  
31 31
    // Test webform_get_submission_count().
32
    // Counting the anonymous submission doesn't work because
33
    // $_SESSION['webform_submission'] is not populated in testing.
32 34
    $this->webformSubmissionExecute('sample');
33 35

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

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

  
43 42
    // Test _webform_submission_prepare_mail().
44 43
    $node = node_load($this->webformForm()->nid);
45 44
    $submission = webform_get_submissions($node->nid);
......
61 60
    $this->assertIdentical($prepared_email['mail_params']['email']['from'], '"from@example.com via Default \'From\' Name" <default-from@example.com>', 'From address is correctly set in _webform_submission_prepare_mail().');
62 61
  }
63 62

  
63
  /**
64
   * Test that the correct submissions are offered for download.
65
   */
66
  public function testWebformSubmissionDownload() {
67
    $this->drupalLogin($this->webform_users['userAccess']);
68
    $this->webformReset();
69

  
70
    // Create Webform which allows drafts and submit a draft.
71
    $webform_settings = array(
72
      'allow_draft' => '1',
73
    );
74
    $this->webformSubmissionExecute('sample', TRUE, $webform_settings);
75

  
76
    $nid = $this->webformForm()->nid;
77

  
78
    // This submit should complete the draft.
79
    $this->webformSubmissionExecute('sample');
80
    // Create another draft.
81
    $this->webformSubmissionExecute('sample', TRUE);
82

  
83
    // Create finished and draft submission as another user.
84
    $this->drupalLogin($this->webform_users['editor']);
85
    $this->webformSubmissionExecute('sample');
86
    $this->webformSubmissionExecute('sample', TRUE);
87

  
88
    // Create finished submission as anonymous.
89
    $this->drupalLogout();
90
    $this->webformSubmissionExecute('sample');
91
    $this->drupalLogin($this->webform_users['editor']);
92

  
93
    // Test webform_download_sids().
94
    $sids = webform_download_sids($nid, array('range_type' => 'new', 'completion_type' => 'finished'), (int) $this->webform_users['editor']->uid);
95
    $this->assertIdentical($sids, array('1', '3', '5'), 'webform_download_sids() shows correct finished submissions.');
96
    $sids = webform_download_sids($nid, array('range_type' => 'new', 'completion_type' => 'draft'), (int) $this->webform_users['editor']->uid);
97
    $this->assertIdentical($sids, array('2', '4'), 'webform_download_sids() shows correct draft submissions.');
98

  
99
    // The timestamp of the Webform results download simulated by the call to
100
    // webform_update_webform_last_download() needs to be after the timestamps
101
    // of the submissions made above. This ensures that the call to time() will
102
    // be after the submission timestamps.
103
    sleep(1);
104

  
105
    // Record that submissions so-far have been downloaded.
106
    // Parameter $sid is not used, so it's value doesn't matter.
107
    webform_update_webform_last_download($this->webformForm(), (int) $this->webform_users['editor']->uid, 0, time());
108

  
109
    // Following the simulated download, there are none to download.
110
    $sids = webform_download_sids($nid, array('range_type' => 'new', 'completion_type' => 'finished'), (int) $this->webform_users['editor']->uid);
111
    $this->assertIdentical($sids, array(), 'webform_download_sids() shows correct finished submissions.');
112
    $sids = webform_download_sids($nid, array('range_type' => 'new', 'completion_type' => 'draft'), (int) $this->webform_users['editor']->uid);
113
    $this->assertIdentical($sids, array(), 'webform_download_sids() shows correct draft submissions.');
114

  
115
    // Finish the draft, add a new draft, and re-check submission lists.
116
    $this->webformSubmissionExecute('sample');
117
    $this->webformSubmissionExecute('sample', TRUE);
118
    $sids = webform_download_sids($nid, array('range_type' => 'new', 'completion_type' => 'finished'), (int) $this->webform_users['editor']->uid);
119
    $this->assertIdentical($sids, array('4'), 'webform_download_sids() shows correct finished submissions.');
120
    $sids = webform_download_sids($nid, array('range_type' => 'new', 'completion_type' => 'draft'), (int) $this->webform_users['editor']->uid);
121
    $this->assertIdentical($sids, array('6'), 'webform_download_sids() shows correct draft submissions.');
122
  }
123

  
124
  /**
125
   * Test Webform submission utility functions.
126
   *
127
   * Test webform_update_webform_last_download() and
128
   * webform_download_last_download_info().
129
   */
130
  public function testWebformSubmissionFunctions() {
131
    $node = (object) array('nid' => 1);
132
    $uid = 1;
133

  
134
    $result = webform_update_webform_last_download($node, $uid, 10, 1000);
135
    $this->assertIdentical($result, MergeQuery::STATUS_INSERT, 'webform_update_webform_last_download() reports successful insert.');
136
    $result = webform_download_last_download_info($node->nid, $uid);
137
    $test = array(
138
      'nid' => '1',
139
      'uid' => '1',
140
      'sid' => '10',
141
      'requested' => '1000',
142
      'serial' => NULL,
143
    );
144
    $this->assertIdentical($result, $test, 'webform_download_last_download_info() returned correct result.');
145

  
146
    $result = webform_update_webform_last_download($node, $uid, 20, 2000);
147
    $this->assertIdentical($result, MergeQuery::STATUS_UPDATE, 'webform_update_webform_last_download() reports successful update.');
148
    $result = webform_download_last_download_info($node->nid, $uid);
149
    $test = array(
150
      'nid' => '1',
151
      'uid' => '1',
152
      'sid' => '20',
153
      'requested' => '2000',
154
      'serial' => NULL,
155
    );
156
    $this->assertIdentical($result, $test, 'webform_download_last_download_info() returned correct result.');
157
  }
158

  
64 159
  /**
65 160
   * Test a submission that uses default values, and check database integrity.
66 161
   */
......
151 246
    $this->assertNoPattern('/ cannot be (longer|shorter) than /');
152 247
  }
153 248

  
249
  /**
250
   * Test webform_submission_data() function.
251
   *
252
   * Do not save components that do not collect data, for example, markup.
253
   */
254
  public function testPlainComponentsSubmission() {
255
    $node = (object) [
256
      'webform' => [
257
        'components' => [
258
          ['type' => 'date'],
259
          ['type' => 'email'],
260
          ['type' => 'grid'],
261
          ['type' => 'hidden'],
262
          ['type' => 'number'],
263
          ['type' => 'select'],
264
          ['type' => 'textarea'],
265
          ['type' => 'textfield'],
266
          ['type' => 'time'],
267
          ['type' => 'fieldset'],
268
          ['type' => 'markup'],
269
          ['type' => 'pagebreak'],
270
        ],
271
      ],
272
    ];
273
    $submitted = [
274
      'date',
275
      'email',
276
      ['value' => 'grid'],
277
      'hidden',
278
      'number',
279
      'select',
280
      'textarea',
281
      'textfield',
282
      'time',
283
      'fieldset',
284
      'markup',
285
      'pagebreak',
286
    ];
287
    $test_data = webform_submission_data($node, $submitted);
288
    $sample_data = [
289
      ['date'],
290
      ['email'],
291
      ['value' => 'grid'],
292
      ['hidden'],
293
      ['number'],
294
      ['select'],
295
      ['textarea'],
296
      ['textfield'],
297
      ['time'],
298
    ];
299
    $this->assertIdentical($test_data, $sample_data, 'webform_submission_data() generates correct data array.');
300
  }
301

  
154 302
  /**
155 303
   * Execute the submission test.
156 304
   *
157 305
   * @param string $value_type
158 306
   *   The values to be submitted to the webform. Either "sample" or "default".
307
   * @param bool $save_draft
308
   *   Whether to save a draft or a final submission.
309
   * @param array $webform_settings
310
   *   Settings to use for this form. Any unspecific settings will be default.
159 311
   */
160
  public function webformSubmissionExecute($value_type = 'sample') {
312
  public function webformSubmissionExecute($value_type = 'sample', $save_draft = FALSE, array $webform_settings = array()) {
161 313
    $path = drupal_get_path('module', 'webform');
162 314
    module_load_include('inc', 'webform', 'includes/webform.submissions');
163 315

  
164 316
    // Create a new Webform test node.
165
    $node = $this->webformForm();
317
    $node = $this->webformForm($webform_settings);
166 318
    $submission_values = $value_type == 'sample' ? $this->webformPost() : array();
167 319

  
168 320
    // Visit the node page with the "foo=bar" query, to test
......
171 323
    $this->assertText($node->title, t('Webform node created and accessible at !url', array('!url' => 'node/' . $node->nid)), t('Webform'));
172 324

  
173 325
    // Submit our test data.
174
    $this->drupalPost(NULL, $submission_values, 'Submit', array(), array(), 'webform-client-form-' . $node->nid);
326
    $this->drupalPost(NULL, $submission_values, $save_draft ? 'Save Draft' : 'Submit', array(), array(), 'webform-client-form-' . $node->nid);
327

  
328
    if ($save_draft) {
329
      $this->assertText(t('Submission saved. You may return to this form later and it will restore the current values.'), t('Save draft message displayed.'), t('Webform'));
330
      return;
331
    }
175 332

  
176 333
    // Confirm that the submission has been created.
177 334
    $this->assertText($node->webform['confirmation'], t('Confirmation message "@confirmation" received.', array('@confirmation' => $node->webform['confirmation'])), t('Webform'));
drupal7/sites/all/modules/webform/tests/WebformTestCase.test
851 851
        ),
852 852
        'error values' => array(
853 853
          '1.5' => t('!name field value of @value must be an integer.', array('!name' => 'Integer', '@value' => '1.5')),
854
          '101' => t('!name field value must be less than @max.', array('!name' => 'Integer', '@max' => '100')),
854
          '101' => t('!name field value must be less than or equal to @max.', array('!name' => 'Integer', '@max' => '100')),
855 855
        ),
856 856
      ),
857 857
      'integer_range' => array(
......
915 915
          'empty' => TRUE,
916 916
        ),
917 917
        'error values' => array(
918
          '-1' => t('!name field value must be greater than @min.', array('!name' => 'Decimal positive', '@min' => '0')),
918
          '-1' => t('!name field value must be greater than or equal to @min.', array('!name' => 'Decimal positive', '@min' => '0')),
919 919
        ),
920 920
      ),
921 921
      'decimal_range' => array(
......
988 988

  
989 989
  /**
990 990
   * Create a sample Webform node.
991
   *
992
   * @param array $webform_settings
993
   *   Settings to use for this form. Any unspecified settings will be default.
991 994
   */
992
  public function webformForm() {
995
  public function webformForm(array $webform_settings = array()) {
993 996
    if (isset($this->_webform_node)) {
994 997
      return $this->_webform_node;
995 998
    }
......
1007 1010
      'title' => 'Test Webform',
1008 1011
      'log' => '',
1009 1012
      'format' => '1',
1010
      'webform' => array(
1013
      'webform' => $webform_settings + array(
1011 1014
        'confirmation' => 'Thanks!',
1012 1015
      ) + webform_node_defaults(),
1013 1016
    );
drupal7/sites/all/modules/webform/webform.api.php
515 515
      // This component may be toggled as required or not. Defaults to TRUE.
516 516
      'required' => TRUE,
517 517

  
518
      // Store data in database. Defaults to TRUE. When FALSE, submission data
519
      // will never be saved. This is for components like fieldset, markup, and
520
      // pagebreak which do not collect data.
521
      'stores_data' => TRUE,
522

  
518 523
      // This component supports a title attribute. Defaults to TRUE.
519 524
      'title' => FALSE,
520 525

  
......
782 787
 *   Keys and titles for default submission information.
783 788
 *
784 789
 * @see hook_webform_results_download_submission_information_data()
790
 * @see hook_webform_results_download_submission_information_info_alter()
785 791
 */
786 792
function hook_webform_results_download_submission_information_info() {
787 793
  return array(
......
790 796
  );
791 797
}
792 798

  
799
/**
800
 * Alter fields in submission data downloads.
801
 *
802
 * @param array $submission_information
803
 *   Keys and titles for default submission information.
804
 *
805
 * @see hook_webform_results_download_submission_information_info()
806
 */
807
function hook_webform_results_download_submission_information_info_alter(array &$submission_information) {
808
  // Unset a property to remove it from submission data downloads.
809
  if (isset($submission_information['webform_ip_address'])) {
810
    unset($submission_information['webform_ip_address']);
811
  }
812
}
813

  
793 814
/**
794 815
 * Return values for submission data download fields.
795 816
 *
......
833 854
function hook_webform_download_sids_query_alter(&$query) {
834 855
  global $user;
835 856

  
836
  // check if component value matches a node ID and author of that node.
857
  // Check if component value matches a node ID and author of that node.
837 858
  $query->join('webform_submitted_data', 'wsd', 'ws.sid = wsd.sid');
838 859
  $query->condition('wsd.cid', 2);
839 860
  $query->join('node', 'n', 'wsd.data = n.nid');
drupal7/sites/all/modules/webform/webform.info
40 40
files[] = tests/WebformTestCase.test
41 41
files[] = tests/WebformUnitTestCase.test
42 42

  
43
; Information added by Drupal.org packaging script on 2020-02-14
44
version = "7.x-4.22"
43
; Information added by Drupal.org packaging script on 2020-06-08
44
version = "7.x-4.23"
45 45
core = "7.x"
46 46
project = "webform"
47
datestamp = "1581709525"
47
datestamp = "1591623589"
drupal7/sites/all/modules/webform/webform.module
1113 1113
        'required' => FALSE,
1114 1114
        'conditional' => FALSE,
1115 1115
        'group' => TRUE,
1116
        'stores_data' => FALSE,
1116 1117
        'title_inline' => FALSE,
1117 1118
        'wrapper_classes' => FALSE,
1118 1119
      ),
......
1158 1159
        'email' => FALSE,
1159 1160
        'required' => FALSE,
1160 1161
        'conditional' => FALSE,
1162
        'stores_data' => FALSE,
1161 1163
        'title_display' => FALSE,
1162 1164
        'private' => FALSE,
1163 1165
        'wrapper_classes' => FALSE,
......
1186 1188
        'description' => FALSE,
1187 1189
        'private' => FALSE,
1188 1190
        'required' => FALSE,
1191
        'stores_data' => FALSE,
1189 1192
        'title_display' => FALSE,
1190 1193
        'wrapper_classes' => FALSE,
1191 1194
        'css_classes' => FALSE,
......
1324 1327
 * have been edited if necessary.
1325 1328
 */
1326 1329
function webform_webform_submission_presave($node, &$submission) {
1330
  module_load_include('inc', 'webform', 'includes/webform.components');
1327 1331
  // Check if there are any file components in this submission and if any of
1328 1332
  // them currently contain files.
1329 1333
  $has_file_components = FALSE;
......
5345 5349
/**
5346 5350
 * Returns the next serial number for a given node and increments it.
5347 5351
 *
5352
 * Return the serial number to be used in the next submission and saves the
5353
 * number after that as the subsequent serial number.
5354
 *
5348 5355
 * @param int $nid
5349 5356
 *   The nid of the node.
5350 5357
 *
......
5356 5363
  // the SELECT and the UPDATE, ensuring that multiple Webform submissions
5357 5364
  // at the same time do not have duplicate numbers. FOR UPDATE must be inside
5358 5365
  // a transaction. The return value of db_transaction() must be assigned or the
5359
  // transaction will commit immediately. The transaction will commit when $txn
5360
  // goes out-of-scope.
5366
  // transaction will commit immediately. The transaction will commit when
5367
  // $transaction goes out-of-scope.
5361 5368
  $transaction = db_transaction();
5362 5369

  
5363
  // Get the next_serial value.
5370
  // Get the value stored in this webform as the next_serial value.
5364 5371
  $next_serial = db_select('webform', 'w')
5365 5372
    // Only add FOR UPDATE when incrementing.
5366 5373
    ->forUpdate()
......
5369 5376
    ->execute()
5370 5377
    ->fetchField();
5371 5378

  
5372
  // $next_serial must be greater than any existing serial number.
5379
  // The value must be greater than $next_serial and any existing serial number.
5373 5380
  $next_serial = max($next_serial, _webform_submission_serial_next_value_used($nid));
5374 5381

  
5375
  // Increment the next_value.
5382
  // Store the value after $next_value for use in the subsequent submission.
5376 5383
  db_update('webform')
5377 5384
    ->fields(array('next_serial' => $next_serial + 1))
5378 5385
    ->condition('nid', $nid)
drupal7/sites/all/modules/webform/webform.tokens.inc
29 29
    'description' => t('The security token used to gain access to this webform submission.'),
30 30
  );
31 31
  $info['tokens']['submission']['date'] = array(
32
    'name' => t('Date submitted'),
33
    'description' => t('The date the webform was first save as draft or completed.'),
32
    'name' => t('Date created'),
33
    'description' => t('The date the webform submission was first saved, either as a draft or completed.'),
34 34
    'type' => 'date',
35 35
  );
36 36
  $info['tokens']['submission']['completed_date'] = array(
37 37
    'name' => t('Date completed'),
38
    'description' => t('The date the webform was first completed (not draft).'),
38
    'description' => t('The date the webform submission was completed (no longer a draft).'),
39 39
    'type' => 'date',
40 40
  );
41 41
  $info['tokens']['submission']['modified_date'] = array(
42 42
    'name' => t('Date modified'),
43
    'description' => t('The date the webform was last saved (draft or completed).'),
43
    'description' => t('The date the webform submission was last saved, either as a draft or completed.'),
44 44
    'type' => 'date',
45 45
  );
46 46
  $info['tokens']['submission']['ip-address'] = array(

Also available in: Unified diff