Projet

Général

Profil

Paste
Télécharger (80,4 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / webform / webform.install @ e9f59ce0

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file
5
 *   Webform module install/schema hooks.
6
 */
7
8
/**
9
 * Implements hook_schema().
10
 */
11
function webform_schema() {
12
  $schema = array();
13
14
  $schema['webform'] = array(
15
    'description' => 'Table for storing additional properties for webform nodes.',
16
    'fields' => array(
17
      'nid' => array(
18
        'description' => 'The node identifier of a webform.',
19
        'type' => 'int',
20
        'unsigned' => TRUE,
21
        'not null' => TRUE,
22
      ),
23 a45e4bc1 Assos Assos
      'next_serial' => array(
24
        'description' => 'The serial number to give to the next submission to this webform.',
25
        'type' => 'int',
26
        'unsigned' => TRUE,
27
        'not null' => TRUE,
28
        'default' => 1,
29
      ),
30 85ad3d82 Assos Assos
      'confirmation' => array(
31
        'description' => 'The confirmation message or URL displayed to the user after submitting a form.',
32
        'type' => 'text',
33
        'not null' => TRUE,
34
      ),
35
      'confirmation_format' => array(
36
        'description' => 'The {filter_format}.format of the confirmation message.',
37
        'type' => 'varchar',
38
        'length' => 255,
39
        'not null' => FALSE,
40
      ),
41
      'redirect_url' => array(
42
        'description' => 'The URL a user is redirected to after submitting a form.',
43
        'type' => 'varchar',
44 a45e4bc1 Assos Assos
        'length' => 2048,
45 85ad3d82 Assos Assos
        'default' => '<confirmation>',
46
      ),
47
      'status' => array(
48
        'description' => 'Boolean value of a webform for open (1) or closed (0).',
49
        'type' => 'int',
50
        'size' => 'tiny',
51
        'not null' => TRUE,
52
        'default' => 1,
53
      ),
54
      'block' => array(
55
         'description' => 'Boolean value for whether this form be available as a block.',
56
         'type' => 'int',
57
         'size' => 'tiny',
58
         'not null' => TRUE,
59
         'default' => 0,
60
      ),
61
      'allow_draft' => array(
62
         'description' => 'Boolean value for whether submissions to this form be saved as a draft.',
63
         'type' => 'int',
64
         'size' => 'tiny',
65
         'not null' => TRUE,
66
         'default' => 0,
67
      ),
68
      'auto_save' => array(
69
         'description' => 'Boolean value for whether submissions to this form should be auto-saved between pages.',
70
         'type' => 'int',
71
         'size' => 'tiny',
72
         'not null' => TRUE,
73
         'default' => 0,
74
      ),
75
      'submit_notice' => array(
76
        'description' => 'Boolean value for whether to show or hide the previous submissions notification.',
77
        'type' => 'int',
78
        'size' => 'tiny',
79
        'not null' => TRUE,
80
        'default' => 1,
81
      ),
82 a45e4bc1 Assos Assos
      'confidential' => array(
83
        'description' => 'Boolean value for whether to anonymize submissions.',
84
        'type' => 'int',
85
        'size' => 'tiny',
86
        'not null' => TRUE,
87
        'default' => 0,
88
      ),
89 85ad3d82 Assos Assos
      'submit_text' => array(
90
        'description' => 'The title of the submit button on the form.',
91
        'type' => 'varchar',
92
        'length' => 255,
93
      ),
94
      'submit_limit' => array(
95
        'description' => 'The number of submissions a single user is allowed to submit within an interval. -1 is unlimited.',
96
        'type' => 'int',
97
        'size' => 'tiny',
98
        'not null' => TRUE,
99
        'default' => -1,
100
      ),
101
      'submit_interval' => array(
102
        'description' => 'The amount of time in seconds that must pass before a user can submit another submission within the set limit.',
103
        'type' => 'int',
104
        'not null' => TRUE,
105
        'default' => -1,
106
      ),
107
      'total_submit_limit' => array(
108
        'description' => 'The total number of submissions allowed within an interval. -1 is unlimited.',
109
        'type' => 'int',
110
        'not null' => TRUE,
111
        'default' => -1,
112
      ),
113
      'total_submit_interval' => array(
114
        'description' => 'The amount of time in seconds that must pass before another submission can be submitted within the set limit.',
115
        'type' => 'int',
116
        'not null' => TRUE,
117
        'default' => -1,
118
      ),
119 a45e4bc1 Assos Assos
      'progressbar_bar' => array(
120
        'description' => 'Boolean value indicating if the bar should be shown as part of the progress bar.',
121
        'type' => 'int',
122
        'size' => 'tiny',
123
        'not null' => TRUE,
124
        'default' => 0,
125
      ),
126
      'progressbar_page_number' => array(
127
        'description' => 'Boolean value indicating if the page number should be shown as part of the progress bar.',
128
        'type' => 'int',
129
        'size' => 'tiny',
130
        'not null' => TRUE,
131
        'default' => 0,
132
      ),
133
      'progressbar_percent' => array(
134
        'description' => 'Boolean value indicating if the percentage complete should be shown as part of the progress bar.',
135
        'type' => 'int',
136
        'size' => 'tiny',
137
        'not null' => TRUE,
138
        'default' => 0,
139
      ),
140
      'progressbar_pagebreak_labels' => array(
141
        'description' => 'Boolean value indicating if the pagebreak labels should be included as part of the progress bar.',
142
        'type' => 'int',
143
        'size' => 'tiny',
144
        'not null' => TRUE,
145
        'default' => 0,
146
      ),
147
      'progressbar_include_confirmation' => array(
148
        'description' => 'Boolean value indicating if the confirmation page should count as a page in the progress bar.',
149
        'type' => 'int',
150
        'size' => 'tiny',
151
        'not null' => TRUE,
152
        'default' => 0,
153
      ),
154
      'progressbar_label_first' => array(
155
        'description' => 'Label for the first page of the progress bar.',
156
        'type' => 'varchar',
157
        'length' => 255,
158
      ),
159
      'progressbar_label_confirmation' => array(
160
        'description' => 'Label for the last page of the progress bar.',
161
        'type' => 'varchar',
162
        'length' => 255,
163
      ),
164
      'preview' => array(
165
        'description' => 'Boolean value indicating if this form includes a page for previewing the submission.',
166
        'type' => 'int',
167
        'size' => 'tiny',
168
        'not null' => TRUE,
169
        'default' => 0,
170
      ),
171
      'preview_next_button_label' => array(
172
        'description' => 'The text for the button that will proceed to the preview page.',
173
        'type' => 'varchar',
174
        'length' => 255,
175
      ),
176
      'preview_prev_button_label' => array(
177
        'description' => 'The text for the button to go backwards from the preview page.',
178
        'type' => 'varchar',
179
        'length' => 255,
180
      ),
181
      'preview_title' => array(
182
        'description' => 'The title of the preview page, as used by the progress bar.',
183
        'type' => 'varchar',
184
        'length' => 255,
185
      ),
186
      'preview_message' => array(
187
        'description' => 'Text shown on the preview page of the form.',
188
        'type' => 'text',
189
        'not null' => TRUE,
190
      ),
191
      'preview_message_format' => array(
192
        'description' => 'The {filter_format}.format of the preview page message.',
193
        'type' => 'varchar',
194
        'length' => 255,
195
      ),
196
      'preview_excluded_components' => array(
197
        'description' => 'Comma-separated list of component IDs that should not be included in this form\'s confirmation page.',
198
        'type' => 'text',
199
        'not null' => TRUE,
200
      ),
201 85ad3d82 Assos Assos
    ),
202
    'primary key' => array('nid'),
203
  );
204
205
  $schema['webform_component'] = array(
206
    'description' => 'Stores information about components for webform nodes.',
207
    'fields' => array(
208
      'nid' => array(
209
        'description' => 'The node identifier of a webform.',
210
        'type' => 'int',
211
        'unsigned' => TRUE,
212
        'not null' => TRUE,
213
        'default' => 0,
214
      ),
215
      'cid' => array(
216
        'description' => 'The identifier for this component within this node, starts at 0 for each node.',
217
        'type' => 'int',
218
        'size' => 'small',
219
        'unsigned' => TRUE,
220
        'not null' => TRUE,
221
        'default' => 0,
222
      ),
223
      'pid' => array(
224
        'description' => 'If this component has a parent fieldset, the cid of that component.',
225
        'type' => 'int',
226
        'size' => 'small',
227
        'unsigned' => TRUE,
228
        'not null' => TRUE,
229
        'default' => 0,
230
      ),
231
      'form_key' => array(
232
        'description' => 'When the form is displayed and processed, this key can be used to reference the results.',
233
        'type' => 'varchar',
234
        'length' => 128,
235
      ),
236
      'name' => array(
237
        'description' => 'The label for this component.',
238 a45e4bc1 Assos Assos
        'type' => 'text',
239
        'not null' => TRUE,
240 85ad3d82 Assos Assos
      ),
241
      'type' => array(
242
        'description' => 'The field type of this component (textfield, select, hidden, etc.).',
243
        'type' => 'varchar',
244
        'length' => 16,
245
      ),
246
      'value' => array(
247
        'description' => 'The default value of the component when displayed to the end-user.',
248
        'type' => 'text',
249
        'not null' => TRUE,
250
      ),
251
      'extra' => array(
252
        'description' => 'Additional information unique to the display or processing of this component.',
253
        'type' => 'text',
254
        'not null' => TRUE,
255
      ),
256 a45e4bc1 Assos Assos
      'required' => array(
257 85ad3d82 Assos Assos
        'description' => 'Boolean flag for if this component is required.',
258
        'type' => 'int',
259
        'size' => 'tiny',
260
        'not null' => TRUE,
261
        'default' => 0,
262
      ),
263
      'weight' => array(
264
        'description' => 'Determines the position of this component in the form.',
265
        'type' => 'int',
266
        'size' => 'small',
267
        'not null' => TRUE,
268
        'default' => 0,
269
      ),
270
    ),
271
    'primary key' => array('nid', 'cid'),
272
  );
273
274 a45e4bc1 Assos Assos
  $schema['webform_conditional'] = array(
275
    'description' => 'Holds information about conditional logic.',
276
    'fields' => array(
277
      'nid' => array(
278
        'description' => 'The node identifier of a webform.',
279
        'type' => 'int',
280
        'unsigned' => TRUE,
281
        'not null' => TRUE,
282
        'default' => 0,
283
      ),
284
      'rgid' => array(
285
        'description' => 'The rule group identifier for this group of rules.',
286
        'type' => 'int',
287
        'size' => 'small',
288
        'unsigned' => TRUE,
289
        'not null' => TRUE,
290
        'default' => 0,
291
      ),
292
      'andor' => array(
293
        'description' => 'Whether to AND or OR the actions in this group. All actions within the same rgid should have the same andor value.',
294
        'type' => 'varchar',
295
        'length' => 128,
296
      ),
297
      'weight' => array(
298
        'description' => 'Determines the position of this conditional compared to others.',
299
        'type' => 'int',
300
        'size' => 'small',
301
        'not null' => TRUE,
302
        'default' => 0,
303
      ),
304
    ),
305
    'primary key' => array('nid', 'rgid'),
306
  );
307
308
  $schema['webform_conditional_rules'] = array(
309
    'description' => 'Holds information about conditional logic.',
310
    'fields' => array(
311
      'nid' => array(
312
        'description' => 'The node identifier of a webform.',
313
        'type' => 'int',
314
        'unsigned' => TRUE,
315
        'not null' => TRUE,
316
        'default' => 0,
317
      ),
318
      'rgid' => array(
319
        'description' => 'The rule group identifier for this group of rules.',
320
        'type' => 'int',
321
        'size' => 'small',
322
        'unsigned' => TRUE,
323
        'not null' => TRUE,
324
        'default' => 0,
325
      ),
326
      'rid' => array(
327
        'description' => 'The rule identifier for this conditional rule.',
328
        'type' => 'int',
329
        'size' => 'small',
330
        'unsigned' => TRUE,
331
        'not null' => TRUE,
332
        'default' => 0,
333
      ),
334
      'source_type' => array(
335
        'description' => 'The type of source on which the conditional is based. Currently always "component". Indicates what type of ID the "source" column contains.',
336
        'type' => 'varchar',
337
        'length' => 128,
338
      ),
339
      'source' => array(
340
        'description' => 'The component ID being used in this condition.',
341
        'type' => 'int',
342
        'size' => 'small',
343
        'unsigned' => TRUE,
344
        'not null' => TRUE,
345
        'default' => 0,
346
      ),
347
      'operator' => array(
348
        'description' => 'Which operator (equal, contains, starts with, etc.) should be used for this comparison between the source and value?',
349
        'type' => 'varchar',
350
        'length' => 128,
351
      ),
352
      'value' => array(
353
        'description' => 'The value to be compared with source.',
354
        'type' => 'text',
355
      ),
356
    ),
357
    'primary key' => array('nid', 'rgid', 'rid'),
358
  );
359
360
  $schema['webform_conditional_actions'] = array(
361
    'description' => 'Holds information about conditional actions.',
362
    'fields' => array(
363
      'nid' => array(
364
        'description' => 'The node identifier of a webform.',
365
        'type' => 'int',
366
        'unsigned' => TRUE,
367
        'not null' => TRUE,
368
        'default' => 0,
369
      ),
370
      'rgid' => array(
371
        'description' => 'The rule group identifier for this group of rules.',
372
        'type' => 'int',
373
        'size' => 'small',
374
        'unsigned' => TRUE,
375
        'not null' => TRUE,
376
        'default' => 0,
377
      ),
378
      'aid' => array(
379
        'description' => 'The rule identifier for this conditional action.',
380
        'type' => 'int',
381
        'size' => 'small',
382
        'unsigned' => TRUE,
383
        'not null' => TRUE,
384
        'default' => 0,
385
      ),
386
      'target_type' => array(
387
        'description' => 'The type of target to be affected. Currently always "component". Indicates what type of ID the "target" column contains.',
388
        'type' => 'varchar',
389
        'length' => 128,
390
      ),
391
      'target' => array(
392
        'description' => 'The ID of the target to be affected. Typically a component ID.',
393
        'type' => 'varchar',
394
        'length' => 128,
395
      ),
396
      'invert' => array(
397
        'description' => 'If inverted, execute when rule(s) are false.',
398
        'type' => 'int',
399
        'size' => 'small',
400
        'unsigned' => TRUE,
401
        'not null' => TRUE,
402
        'default' => 0,
403
      ),
404
      'action' => array(
405
        'description' => 'The action to be performed on the target.',
406
        'type' => 'varchar',
407
        'length' => 128,
408
      ),
409
      'argument' => array(
410
        'description' => 'Optional argument for action.',
411
        'type' => 'text',
412
      ),
413
    ),
414
    'primary key' => array('nid', 'rgid', 'aid'),
415
  );
416
417 85ad3d82 Assos Assos
  $schema['webform_emails'] = array(
418
    'description' => 'Holds information regarding e-mails that should be sent upon submitting a webform',
419
    'fields' => array(
420
      'nid' => array(
421
        'description' => 'The node identifier of a webform.',
422
        'type' => 'int',
423
        'unsigned' => TRUE,
424
        'not null' => TRUE,
425
        'default' => 0,
426
      ),
427
      'eid' => array(
428
        'description' => 'The e-mail identifier for this row\'s settings.',
429
        'type' => 'int',
430
        'unsigned' => TRUE,
431
        'size' => 'small',
432
        'not null' => TRUE,
433
        'default' => 0,
434
      ),
435
      'email' => array(
436
        'description' => 'The e-mail address that will be sent to upon submission. This may be an e-mail address, the special key "default" or a numeric value. If a numeric value is used, the value of a component will be substituted on submission.',
437
        'type' => 'text',
438
        'not null' => FALSE,
439
      ),
440
      'subject' => array(
441
        'description' => 'The e-mail subject that will be used. This may be a string, the special key "default" or a numeric value. If a numeric value is used, the value of a component will be substituted on submission.',
442 a45e4bc1 Assos Assos
        'type' => 'text',
443 85ad3d82 Assos Assos
        'not null' => FALSE,
444
      ),
445
      'from_name' => array(
446
        'description' => 'The e-mail "from" name that will be used. This may be a string, the special key "default" or a numeric value. If a numeric value is used, the value of a component will be substituted on submission.',
447 a45e4bc1 Assos Assos
        'type' => 'text',
448 85ad3d82 Assos Assos
        'not null' => FALSE,
449
      ),
450
      'from_address' => array(
451
        'description' => 'The e-mail "from" e-mail address that will be used. This may be a string, the special key "default" or a numeric value. If a numeric value is used, the value of a component will be substituted on submission.',
452 a45e4bc1 Assos Assos
        'type' => 'text',
453 85ad3d82 Assos Assos
        'not null' => FALSE,
454
      ),
455
      'template' => array(
456
        'description' => 'A template that will be used for the sent e-mail. This may be a string or the special key "default", which will use the template provided by the theming layer.',
457
        'type' => 'text',
458
        'not null' => FALSE,
459
      ),
460
      'excluded_components' => array(
461 a45e4bc1 Assos Assos
        'description' => 'A list of components that will not be included in the [submission:values] token. A list of CIDs separated by commas.',
462 85ad3d82 Assos Assos
        'type' => 'text',
463
        'not null' => TRUE,
464
      ),
465
      'html' => array(
466
        'description' => 'Determines if the e-mail will be sent in an HTML format. Requires Mime Mail module.',
467
        'type' => 'int',
468
        'unsigned' => TRUE,
469
        'size' => 'tiny',
470
        'not null' => TRUE,
471
        'default' => 0,
472
      ),
473
      'attachments' => array(
474
        'description' => 'Determines if the e-mail will include file attachments. Requires Mime Mail module.',
475
        'type' => 'int',
476
        'unsigned' => TRUE,
477
        'size' => 'tiny',
478
        'not null' => TRUE,
479
        'default' => 0,
480
      ),
481 a45e4bc1 Assos Assos
      'exclude_empty' => array(
482
        'description' => 'Determines if the e-mail will include component with an empty value.',
483
        'type' => 'int',
484
        'unsigned' => TRUE,
485
        'size' => 'tiny',
486
        'not null' => TRUE,
487
        'default' => 0,
488
      ),
489
      'extra' => array(
490
        'description' => 'A serialized array of additional options for the e-mail configuration, including value mapping for the TO and FROM addresses for select lists.',
491
        'type' => 'text',
492
        'not null' => TRUE,
493
      ),
494
      'status' => array(
495
        'description' => 'Whether this email is enabled.',
496
        'type' => 'int',
497
        'unsigned' => TRUE,
498
        'size' => 'tiny',
499
        'not null' => TRUE,
500
        'default' => 1,
501
      ),
502 85ad3d82 Assos Assos
    ),
503
    'primary key' => array('nid', 'eid'),
504
  );
505
506
  $schema['webform_roles'] = array(
507
    'description' => 'Holds access information regarding which roles are allowed to submit which webform nodes. Does not prevent access to the webform node entirely, use the {node_access} table for that purpose.',
508
    'fields' => array(
509
      'nid' => array(
510
        'description' => 'The node identifier of a webform.',
511
        'type' => 'int',
512
        'unsigned' => TRUE,
513
        'not null' => TRUE,
514
        'default' => 0,
515
      ),
516
      'rid' => array(
517
        'description' => 'The role identifier.',
518
        'type' => 'int',
519
        'unsigned' => TRUE,
520
        'not null' => TRUE,
521
        'default' => 0,
522
      ),
523
    ),
524
    'primary key' => array('nid', 'rid'),
525
  );
526
527
  $schema['webform_submissions'] = array(
528
    'description' => 'Holds general information about submissions outside of field values.',
529
    'fields' => array(
530
      'sid' => array(
531
        'description' => 'The unique identifier for this submission.',
532
        'type' => 'serial',
533
        'unsigned' => TRUE,
534
        'not null' => TRUE,
535
      ),
536
      'nid' => array(
537
        'description' => 'The node identifier of a webform.',
538
        'type' => 'int',
539
        'unsigned' => TRUE,
540
        'not null' => TRUE,
541
        'default' => 0,
542
      ),
543 a45e4bc1 Assos Assos
      'serial' => array(
544
        'description' => 'The serial number of this submission.',
545
        'type' => 'int',
546
        'unsigned' => TRUE,
547
        'not null' => TRUE,
548
      ),
549 85ad3d82 Assos Assos
      'uid' => array(
550
        'description' => 'The id of the user that completed this submission.',
551
        'type' => 'int',
552
        'unsigned' => TRUE,
553
        'not null' => TRUE,
554
        'default' => 0,
555
      ),
556
      'is_draft' => array(
557
         'description' => 'Is this a draft of the submission?',
558
         'type' => 'int',
559
         'size' => 'tiny',
560
         'not null' => TRUE,
561
         'default' => 0,
562
      ),
563 a45e4bc1 Assos Assos
      'highest_valid_page' => array(
564
         'description' => 'For drafts, the highest validated page number.',
565
         'type' => 'int',
566
         'size' => 'small',
567
         'not null' => TRUE,
568
         'default' => 0,
569
      ),
570 85ad3d82 Assos Assos
      'submitted' => array(
571 a45e4bc1 Assos Assos
        'description' => 'Timestamp when the form was first saved as draft or submitted.',
572
        'type' => 'int',
573
        'not null' => TRUE,
574
        'default' => 0,
575
      ),
576
      'completed' => array(
577
        'description' => 'Timestamp when the form was submitted as complete (not draft).',
578
        'type' => 'int',
579
        'not null' => TRUE,
580
        'default' => 0,
581
      ),
582
      'modified' => array(
583
        'description' => 'Timestamp when the form was last saved (complete or draft).',
584 85ad3d82 Assos Assos
        'type' => 'int',
585
        'not null' => TRUE,
586
        'default' => 0,
587
      ),
588
      'remote_addr' => array(
589
        'description' => 'The IP address of the user that submitted the form.',
590
        'type' => 'varchar',
591
        'length' => 128,
592
      ),
593
    ),
594
    'primary key' => array('sid'),
595
    'unique keys' => array(
596
      'sid_nid' => array('sid', 'nid'),
597 a45e4bc1 Assos Assos
      'nid_serial' => array('nid', 'serial'),
598 85ad3d82 Assos Assos
    ),
599
    'indexes' => array(
600
      'nid_uid_sid' => array('nid', 'uid', 'sid'),
601
      'nid_sid' => array('nid', 'sid'),
602
    ),
603
  );
604
605
  $schema['webform_submitted_data'] = array(
606
    'description' => 'Stores all submitted field data for webform submissions.',
607
    'fields' => array(
608
      'nid' => array(
609
        'description' => 'The node identifier of a webform.',
610
        'type' => 'int',
611
        'unsigned' => TRUE,
612
        'not null' => TRUE,
613
        'default' => 0,
614
      ),
615
      'sid' => array(
616
        'description' => 'The unique identifier for this submission.',
617
        'type' => 'int',
618
        'unsigned' => TRUE,
619
        'not null' => TRUE,
620
        'default' => 0,
621
      ),
622
      'cid' => array(
623
        'description' => 'The identifier for this component within this node, starts at 0 for each node.',
624
        'type' => 'int',
625
        'size' => 'small',
626
        'unsigned' => TRUE,
627
        'not null' => TRUE,
628
        'default' => 0,
629
      ),
630
      'no' => array(
631
        'description' => 'Usually this value is 0, but if a field has multiple values (such as a time or date), it may require multiple rows in the database.',
632
        'type' => 'varchar',
633
        'length' => 128,
634
        'not null' => TRUE,
635
        'default' => '0',
636
      ),
637
      'data' => array(
638
        'description' => 'The submitted value of this field, may be serialized for some components.',
639
        'type' => 'text',
640
        'size' => 'medium',
641
        'not null' => TRUE,
642
      ),
643
    ),
644
    'primary key' => array('nid', 'sid', 'cid', 'no'),
645
    'indexes' => array(
646
      'nid' => array('nid'),
647
      'sid_nid' => array('sid', 'nid'),
648 a45e4bc1 Assos Assos
      // For all but MS SQL Server databases, 64-character index is created on the data column after the schema is installed.
649 85ad3d82 Assos Assos
    ),
650
  );
651
652
  $schema['webform_last_download'] = array(
653
   'description' => 'Stores last submission number per user download.',
654
    'fields' => array(
655
      'nid' => array(
656
        'description' => 'The node identifier of a webform.',
657
        'type' => 'int',
658
        'unsigned' => TRUE,
659
        'not null' => TRUE,
660
        'default' => 0,
661
      ),
662
      'uid' => array(
663
       'description' => 'The user identifier.',
664
        'type' => 'int',
665
        'unsigned' => TRUE,
666
        'not null' => TRUE,
667
        'default' => 0,
668
      ),
669
     'sid' => array(
670
        'description' => 'The last downloaded submission number.',
671
        'type' => 'int',
672
        'unsigned' => TRUE,
673
        'not null' => TRUE,
674
        'default' => 0,
675
      ),
676
     'requested' => array(
677
        'description' => 'Timestamp of last download request.',
678
        'type' => 'int',
679
        'unsigned' => TRUE,
680
        'not null' => TRUE,
681
        'default' => 0,
682
      ),
683
    ),
684
    'primary key' => array('nid', 'uid'),
685
  );
686
687
  return $schema;
688
}
689
690 a45e4bc1 Assos Assos
691
/**
692
 * Implements hook_requirements().
693
 */
694
function webform_requirements($phase) {
695
  $requirements = array();
696
  $t = get_t();
697
698
  // Ensure cURL exists if SimpleTest hasn't checked it already.
699
  if (!class_exists('ZipArchive')) {
700
    $requirements['webform_zip'] = array(
701
      'title' => $t('Zip archive support'),
702
      'value' => $t('Missing'),
703
      'severity' => REQUIREMENT_WARNING,
704
      'description' => $t('PHP does not have the zip archive extension available. Webform module requires zip support for exporting submissions to Microsoft Excel.'),
705
    );
706
  }
707
  // Though the .info file specifies PHP version as well, this will prevent
708
  // users from upgrading from 3.x if their PHP version is too old.
709
  if (version_compare(phpversion(), '5.3') < 0) {
710
    $requirements['webform_php'] = array(
711 ba09eb79 Assos Assos
      'title' => $t('Webform PHP requirement'),
712 a45e4bc1 Assos Assos
      'value' => phpversion(),
713
      'severity' => REQUIREMENT_ERROR,
714
      'description' => $t('Webform requires PHP 5.3 or higher.'),
715
    );
716
  }
717 ba09eb79 Assos Assos
  // Ensure that views is enabled as it is a new .info requirement starting
718
  // with version 7.x-4.0rc1. On installation, the .info file is sufficient to
719
  // cause the dependencies to be installed. On update, update.php will
720
  // respect this hook_requirements implementation, but as of drush 6.3.0 and
721
  // drush 7.0.0, drush updatedb will not. See:
722
  // https://github.com/drush-ops/drush/issues/1427
723
  if ($phase != 'install' && !module_exists('views')) {
724
    $requirements['webform_views'] = array(
725
      'title' => $t('Webform Views requirement'),
726
      'value' => $t('Missing'),
727
      'severity' => REQUIREMENT_ERROR,
728
      'description' => $t('Webform requires Views, which is not installed and enabled.'),
729
    );
730
  }
731 a45e4bc1 Assos Assos
732
  return $requirements;
733
}
734
735 85ad3d82 Assos Assos
/**
736
 * Implements hook_install().
737
 */
738
function webform_install() {
739
  module_load_include('inc', 'node', 'content_types');
740
  db_update('system')
741
    ->condition('name', 'webform')
742
    ->condition('type', 'module')
743
    ->fields(array('weight' => -1))
744
    ->execute();
745
746
  // Optionally create the default webform type.
747
  if (variable_get('webform_install_create_content_type', TRUE)) {
748
    $webform_type = array(
749
      'type' => 'webform',
750
      'name' => st('Webform'),
751
      'base' => 'node_content',
752
      'description' => st('Create a new form or questionnaire accessible to users. Submission results and statistics are recorded and accessible to privileged users.'),
753
      'custom' => TRUE,
754
      'modified' => TRUE,
755
      'locked' => FALSE,
756
    );
757
    $webform_type = node_type_set_defaults($webform_type);
758
    node_type_save($webform_type);
759 a45e4bc1 Assos Assos
    // Enable webform components by default on Webform nodes.
760
    variable_set('webform_node_webform', TRUE);
761
    // Now that a webform node type has been created, reset the cache of the
762
    // node types that support webforms. This is needed for tests which will
763
    // create nodes in the same execution.
764
    drupal_static_reset('webform_node_types');
765
    if (variable_get('webform_install_add_body_field', FALSE)) {
766 3753f249 Assos Assos
      node_add_body_field($webform_type);
767
    }
768 a45e4bc1 Assos Assos
    // Disable comments by default on Webform nodes.
769
    variable_set('comment_webform', '0');
770
  }
771
  else {
772
    variable_set('webform_node_types_primary', array());
773
  }
774
775
  // Note: MS SQL Server does not support size-limited indexes and the column
776
  // type (text) is too big to fit inside index size limits.
777
  if (!db_index_exists('webform_submitted_data', 'data') && db_driver() != 'sqlsrv') {
778
    db_add_index('webform_submitted_data', 'data', array(array('data', 64)));
779 85ad3d82 Assos Assos
  }
780
}
781
782
/**
783
 * Implements hook_uninstall().
784
 */
785
function webform_uninstall() {
786
  // Unset webform variables.
787 a45e4bc1 Assos Assos
  variable_del('webform_blocks');
788
  variable_del('webform_tracking_mode');
789
  variable_del('webform_allowed_tags');
790
  variable_del('webform_email_address_format');
791
  variable_del('webform_email_address_individual');
792 85ad3d82 Assos Assos
  variable_del('webform_default_from_name');
793 a45e4bc1 Assos Assos
  variable_del('webform_default_from_address');
794 85ad3d82 Assos Assos
  variable_del('webform_default_subject');
795 a45e4bc1 Assos Assos
  variable_del('webform_email_replyto');
796
  variable_del('webform_email_html_capable');
797 85ad3d82 Assos Assos
  variable_del('webform_default_format');
798
  variable_del('webform_format_override');
799 a45e4bc1 Assos Assos
  variable_del('webform_email_select_max');
800
  variable_del('webform_node_types_primary');
801
  variable_del('webform_date_type');
802 3753f249 Assos Assos
  variable_del('webform_export_format');
803 a45e4bc1 Assos Assos
  variable_del('webform_csv_delimiter');
804 01d522a6 Assos Assos
  variable_del('webform_csv_line_ending');
805 a45e4bc1 Assos Assos
  variable_del('webform_export_wordwrap');
806
  variable_del('webform_excel_legacy_exporter');
807
  variable_del('webform_progressbar_style');
808
  variable_del('webform_progressbar_label_first');
809
  variable_del('webform_progressbar_label_confirmation');
810
  variable_del('webform_table');
811 3753f249 Assos Assos
  variable_del('webform_submission_access_control');
812 ba09eb79 Assos Assos
  variable_del('webform_token_access');
813 3753f249 Assos Assos
  variable_del('webform_update_batch_size');
814 a45e4bc1 Assos Assos
  variable_del('webform_disabled_components');
815
816
  foreach (node_type_get_names() as $type => $name) {
817
    variable_del('webform_node_' . $type);
818
  }
819 85ad3d82 Assos Assos
820
  $component_list = array();
821
  $path = drupal_get_path('module', 'webform') . '/components';
822
  $files = file_scan_directory($path, '/^.*\.inc$/');
823
  foreach ($files as $filename => $file) {
824
    variable_del('webform_enable_' . $file->name, 1);
825
  }
826
827
  // Delete uploaded files.
828
  $filepath = file_build_uri('webform');
829
  file_unmanaged_delete_recursive($filepath);
830 a45e4bc1 Assos Assos
831
  // Delete the content type "webform" if:
832
  //   a) there are no existing nodes of type webform and
833
  //   b) no additional fields have been defined for node type webform, beyond
834
  //      the default body field.
835
  $query = new EntityFieldQuery();
836
  $results = $query->entityCondition('entity_type', 'node')
837
    ->entityCondition('bundle', 'webform')
838
    ->range(0, 1)
839
    ->execute();
840
  $instances = field_info_instances('node', 'webform');
841
  unset($instances['body']);
842
  if (!$results && !$instances) {
843
    node_type_delete('webform');
844
    drupal_flush_all_caches();
845
  }
846
847 85ad3d82 Assos Assos
}
848
849
/**
850
 * Set the minimum upgrade version.
851
 *
852
 * Currently you cannot upgrade from 2.x in Drupal 6 to 3.x in Drupal 7. However
853
 * there are no database changes between the 3.x versions, so no update is
854
 * needed at all to move from 3.x in Drupal 6 to Drupal 7.
855
 */
856
function webform_update_last_removed() {
857
  return 6313;
858
}
859
860
/**
861
 * Allow the confirmation format column to have a NULL value.
862
 */
863
function webform_update_7301() {
864
  // These changes are modeled after user_update_7010().
865
  db_change_field('webform', 'confirmation_format', 'confirmation_format', array(
866
    'description' => 'The {filter_format}.format of the confirmation message.',
867
    'type' => 'int',
868
    'unsigned' => TRUE,
869
    'not null' => FALSE,
870
  ));
871
  db_update('webform')
872
    ->fields(array('confirmation_format' => NULL))
873
    ->condition('confirmation', '')
874
    ->condition('confirmation_format', 0)
875
    ->execute();
876
  $existing_formats = db_query("SELECT format FROM {filter_format}")->fetchCol();
877
  $default_format = variable_get('filter_default_format', 1);
878
879
  // Since Webform may be updated separately from Drupal core, not all format
880
  // names may be numbers when running this update.
881
  $numeric_formats = array();
882
  foreach ($existing_formats as $format_name) {
883
    if (is_numeric($format_name)) {
884
      $numeric_formats[] = (int) $format_name;
885
    }
886
  }
887
888
  $query = db_update('webform')
889
    ->fields(array('confirmation_format' => $default_format))
890
    ->isNotNull('confirmation_format');
891
892
  if (!empty($numeric_formats)) {
893
    $query->condition('confirmation_format', $numeric_formats, 'NOT IN');
894
  }
895
896
  $query->execute();
897
}
898
899
/**
900
 * Add columns for e-mail HTML and attachment settings.
901
 */
902
function webform_update_7302() {
903
  if (!db_field_exists('webform_emails', 'html')) {
904
    db_add_field('webform_emails', 'html', array('type' => 'int', 'size' => 'tiny', 'unsigned' => TRUE, 'default' => 0, 'not null' => TRUE));
905
    db_add_field('webform_emails', 'attachments', array('type' => 'int', 'size' => 'tiny', 'unsigned' => TRUE, 'default' => 0, 'not null' => TRUE));
906
  }
907
}
908
909
/**
910
 * Set the default for the "submit_notice" column to 1.
911
 */
912
function webform_update_7303() {
913
  db_change_field('webform', 'submit_notice', 'submit_notice', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 1));
914
}
915
916
/**
917
 * Add field for block feature and redirection setting.
918
 */
919
function webform_update_7304() {
920
  if (!db_field_exists('webform', 'block')) {
921
    db_add_field('webform', 'block', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
922
    db_change_field('webform', 'redirect_url', 'redirect_url', array('type' => 'varchar', 'length' => 255, 'default' => '<confirmation>'));
923
    db_update('webform')
924
      ->fields(array('redirect_url' => 'confirmation'))
925
      ->condition('redirect_url', '')
926
      ->execute();
927
  }
928
}
929
930
/**
931
 * Set additional_validate and additional_submit columns to allow NULL.
932
 */
933
function webform_update_7305() {
934
  if (db_field_exists('webform', 'additional_validate')) {
935
    db_change_field('webform', 'additional_validate', 'additional_validate', array('type' => 'text', 'not null' => FALSE));
936
    db_change_field('webform', 'additional_submit', 'additional_submit', array('type' => 'text', 'not null' => FALSE));
937
  }
938
}
939
940
/**
941
 * Add column for webform status (open or closed).
942
 */
943
function webform_update_7306() {
944
  if (!db_field_exists('webform', 'status')) {
945
    db_add_field('webform', 'status', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 1));
946
  }
947
}
948
949
/**
950
 * Update the confirmation_format column for default text format changes.
951
 */
952
function webform_update_7307() {
953
  // Update removed and moved to webform_update_7301().
954
  // See http://drupal.org/node/976102.
955
}
956
957
/**
958
 * Update the confirmation_format column to allow it to store strings.
959
 */
960
function webform_update_7308() {
961
  db_change_field('webform', 'confirmation_format', 'confirmation_format', array(
962
    'description' => 'The {filter_format}.format of the confirmation message.',
963
    'type' => 'varchar',
964
    'length' => 255,
965
    'not null' => FALSE,
966
  ));
967
}
968
969
/**
970
 * Add the ability to auto-save as draft between pages.
971
 */
972
function webform_update_7309() {
973
  if (!db_field_exists('webform', 'auto_save')) {
974
    db_add_field('webform', 'auto_save', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
975
  }
976
}
977
978
/**
979
 * Remove orphaned and unnecessary rows in the webform table.
980
 */
981
function webform_update_7310() {
982
  $result = db_query("SELECT nid FROM {webform} WHERE
983
    nid NOT IN
984
    (SELECT DISTINCT(w1.nid) FROM {webform} w1 INNER JOIN {webform_component} wc ON w1.nid = wc.nid)
985
    AND nid NOT IN
986
    (SELECT w2.nid FROM {webform} w2 INNER JOIN {node} n ON w2.nid = n.nid WHERE n.type = 'webform')"
987
  );
988
  $empty_nids = array();
989
  foreach ($result as $row) {
990
    $empty_nids[] = $row->nid;
991
  }
992
  if (!empty($empty_nids)) {
993
    db_delete('webform')->condition('nid', $empty_nids, 'IN')->execute();
994
  }
995
}
996
997
/**
998
 * Add an index for nid_uid_sid to webform_submissions.
999
 */
1000
function webform_update_7311() {
1001
  if (!db_index_exists('webform_submissions', 'nid_uid_sid')) {
1002
    db_add_index('webform_submissions', 'nid_uid_sid', array('nid', 'uid', 'sid'));
1003
  }
1004
}
1005
1006
/**
1007
 * Remove unused Webform variables.
1008
 */
1009
function webform_update_7312() {
1010
  variable_del('node_types');
1011
  variable_del('components');
1012
}
1013
1014
/**
1015
 * Convert the Date component start and end year options to start and end date.
1016
 */
1017
function webform_update_7313() {
1018
  $result = db_select('webform_component', 'wc', array('fetch' => PDO::FETCH_ASSOC))
1019
    ->fields('wc')
1020
    ->condition('type', 'date')
1021
    ->execute();
1022
  foreach ($result as $component) {
1023
    $component['extra'] = unserialize($component['extra']);
1024
    if (!isset($component['extra']['start_date']) && !isset($component['end_date'])) {
1025
      foreach (array('year_start' => 'start_date', 'year_end' => 'end_date') as $key => $replacement) {
1026
        $value = isset($component['extra'][$key]) ? trim($component['extra'][$key]) : '';
1027
        // Relative years.
1028
        if (preg_match('/[-+][ ]*[0-9]+/', $value)) {
1029
          $component['extra'][$replacement] = ($value == 1) ? ($value . ' year') : ($value . ' years');
1030
        }
1031
        // Absolute years.
1032
        elseif (is_numeric($value)) {
1033
          $component['extra'][$replacement] = 'Dec 31 ' . $value;
1034
        }
1035
        unset($component['extra'][$key]);
1036
      }
1037
      $component['extra'] = serialize($component['extra']);
1038
      drupal_write_record('webform_component', $component, array('nid', 'cid'));
1039
    }
1040
  }
1041
}
1042
1043
/**
1044
 * Add webform_last_download table to store last downloaded sid per user.
1045
 */
1046
function webform_update_7314() {
1047
  // Safety check to prevent recreating the webform_last_download table.
1048
  if (db_table_exists('webform_last_download')) {
1049
    return;
1050
  }
1051
1052
  $schema['webform_last_download'] = array(
1053
    'description' => 'Stores last submission number per user download.',
1054
    'fields' => array(
1055
      'nid' => array(
1056
        'description' => 'The node identifier of a webform.',
1057
        'type' => 'int',
1058
        'unsigned' => TRUE,
1059
        'not null' => TRUE,
1060
        'default' => 0,
1061
      ),
1062
      'uid' => array(
1063
        'description' => 'The user identifier.',
1064
        'type' => 'int',
1065
        'unsigned' => TRUE,
1066
        'not null' => TRUE,
1067
        'default' => 0,
1068
      ),
1069
      'sid' => array(
1070
        'description' => 'The last downloaded submission number.',
1071
        'type' => 'int',
1072
        'unsigned' => TRUE,
1073
        'not null' => TRUE,
1074
        'default' => 0,
1075
      ),
1076
    ),
1077
    'primary key' => array('nid', 'uid'),
1078
  );
1079
  db_create_table('webform_last_download', $schema['webform_last_download']);
1080
}
1081
1082
/**
1083
 * Add column for timestamp of last requested CSV download.
1084
 */
1085
function webform_update_7315() {
1086
  if (!db_field_exists('webform_last_download', 'requested')) {
1087 a45e4bc1 Assos Assos
    db_add_field('webform_last_download', 'requested', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
1088 85ad3d82 Assos Assos
  }
1089
}
1090
1091
/**
1092
 * Add additional columns for total submission limit.
1093
 */
1094
function webform_update_7316() {
1095
  if (!db_field_exists('webform', 'total_submit_limit')) {
1096
    db_add_field('webform', 'total_submit_limit', array('type' => 'int', 'not null' => TRUE, 'default' => -1));
1097
  }
1098
1099
  if (!db_field_exists('webform', 'total_submit_interval')) {
1100
    db_add_field('webform', 'total_submit_interval', array('type' => 'int', 'not null' => TRUE, 'default' => -1));
1101
  }
1102
}
1103
1104
/**
1105
 * Add an index for 'nid_sid' to webform_submissions.
1106
 */
1107
function webform_update_7317() {
1108
  // Even though we already have an index 'nid_uid_sid', adding the index for
1109
  // 'nid_sid' saves us a tablesort on the node/x/webform-results page.
1110
  if (!db_index_exists('webform_submissions', 'nid_sid')) {
1111
    db_add_index('webform_submissions', 'nid_sid', array('nid', 'sid'));
1112
  }
1113
}
1114
1115
/**
1116
 * Upgrade file components to support the new AJAX-upload element.
1117
 */
1118
function webform_update_7318() {
1119
  $result = db_select('webform_component', 'wc', array('fetch' => PDO::FETCH_ASSOC))
1120
    ->fields('wc')
1121
    ->condition('type', 'file')
1122
    ->execute();
1123
  foreach ($result as $component) {
1124
    $component['extra'] = unserialize($component['extra']);
1125
    if (!isset($component['extra']['directory'])) {
1126
      $component['extra']['directory'] = $component['extra']['savelocation'];
1127
      $component['extra']['scheme'] = file_default_scheme();
1128
      $component['extra']['filtering']['size'] = $component['extra']['filtering']['size'] . ' KB';
1129
      unset($component['extra']['savelocation']);
1130
      $component['extra'] = serialize($component['extra']);
1131
      drupal_write_record('webform_component', $component, array('nid', 'cid'));
1132
    }
1133
  }
1134
1135
  return t('File components updated to support AJAX uploading.');
1136
}
1137
1138
/**
1139
 * Add file usage entries for all files uploaded through Webform.
1140
 */
1141
function webform_update_7319(&$sandbox) {
1142
  if (!isset($sandbox['progress'])) {
1143
    // Initialize batch update information.
1144
    $sandbox['progress'] = 0;
1145
    $sandbox['last_fid_processed'] = -1;
1146
    $sandbox['max'] = db_select('file_managed')
1147
      ->condition('uri', '%' . db_like('://webform/') . '%', 'LIKE')
1148
      ->countQuery()
1149
      ->execute()
1150
      ->fetchField();
1151
  }
1152
1153
  // Process all files attached to a given revision during the same batch.
1154 a45e4bc1 Assos Assos
  $limit = webform_variable_get('webform_update_batch_size');
1155 85ad3d82 Assos Assos
  $files = db_select('file_managed', 'f')
1156
    ->fields('f')
1157
    ->condition('uri', '%' . db_like('://webform/') . '%', 'LIKE')
1158
    ->condition('fid', $sandbox['last_fid_processed'], '>')
1159
    ->orderBy('fid', 'ASC')
1160
    ->range(0, $limit)
1161
    ->execute()
1162
    ->fetchAllAssoc('fid', PDO::FETCH_ASSOC);
1163
1164
  // Determine each submission with which a file is associated.
1165
  if (!empty($files)) {
1166
    foreach ($files as $fid => $file) {
1167
      $file = (object) $file;
1168
      $sids = db_query('SELECT wsd.sid FROM {webform_component} wc INNER JOIN {webform_submitted_data} wsd ON wc.nid = wsd.nid AND wc.type = :file WHERE data = :fid', array(':file' => 'file', ':fid' => $file->fid))->fetchAllAssoc('sid', PDO::FETCH_ASSOC);
1169
      foreach ($sids as $sid => $row) {
1170
        // We use a db_merge() instead of file_usage_add() to prevent problems
1171
        // in the event this update was run twice. No file provided by Webform
1172
        // should ever be in use more than once at this point.
1173
        db_merge('file_usage')
1174
          ->key(array(
1175
            'fid' => $file->fid,
1176
            'type' => 'submission',
1177
            'module' => 'webform',
1178
            'id' => $sid,
1179
          ))
1180
          ->fields(array(
1181
            'count' => 1,
1182
          ))
1183
          ->execute();
1184
      }
1185
1186
      // Update our progress information for the batch update.
1187
      $sandbox['progress']++;
1188
      $sandbox['last_fid_processed'] = $file->fid;
1189
    }
1190
  }
1191
1192
  // If less than limit was processed, the update process is finished.
1193
  if (count($files) < $limit || $sandbox['progress'] == $sandbox['max']) {
1194
    $finished = TRUE;
1195
  }
1196
1197
  // If there's no max value then there's nothing to update and we're finished.
1198
  if (empty($sandbox['max']) || isset($finished)) {
1199
    return t('Webform file entries created in the file_usage table.');
1200
  }
1201
  else {
1202
    // Indicate our current progress to the batch update system.
1203
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
1204
  }
1205
}
1206
1207
/**
1208
 * Mark files uploaded through Webform that report active usage permanent.
1209
 */
1210
function webform_update_7320() {
1211
  db_query("UPDATE {file_managed} SET status = 1 WHERE fid IN (SELECT fid FROM {file_usage} WHERE module = :module_name)", array(':module_name' => 'webform'));
1212
}
1213
1214
/**
1215 a45e4bc1 Assos Assos
 * Rewrite token replacement system to use D7 tokens.
1216
 *
1217
 * If needed, please download and install the Token module from drupal.org.
1218
 * Otherwise some tokens will not be rendered.
1219
 */
1220
function webform_update_7401(&$sandbox) {
1221
  // Define replacements.
1222
  $patterns = array(
1223
    '%username',
1224
    '%useremail',
1225
    '%uid',
1226
    '%date',
1227
    '%ip_address',
1228
    '%site',
1229
    '%nid',
1230
    '%title',
1231
    '%email_values',
1232
    '%submission_url',
1233
    '%sid',
1234
    '%server[REQUEST_URI]',
1235
    '][', // Used to convert nested arrays of %value and %email.
1236
  );
1237
  $replacements = array(
1238
    '[current-user:name]',
1239
    '[current-user:mail]',
1240
    '[current-user:uid]',
1241
    '[submission:date:long]',
1242
    '[current-user:ip-address]',
1243
    '[site:name]',
1244
    '[node:nid]',
1245
    '[node:title]',
1246
    '[submission:values]',
1247
    '[submission:url]',
1248
    '[submission:sid]',
1249
    '[current-page:url]',
1250
    ':', // Replace "][" with ":" for %value and %email.
1251
  );
1252
  $dpatterns = array(
1253
    '/%get\[([^\]]+)\]/m',
1254
    '/%email\[([^% \n\r\t]+)?\]/m',
1255
    '/%value\[([^% \n\r\t]+)?\]/m',
1256
    '/%profile\[([^\]]+)\]/m',
1257
  );
1258
  $dreplacements = array(
1259
    '[current-page:query:$1]',
1260
    '[submission:values:$1]',
1261
    '[submission:values:$1:nolabel]',
1262
    '[current-user:$1]',
1263
  );
1264
1265
  $limit = webform_variable_get('webform_update_batch_size');
1266
  $processed_count = _webform_update_7401_batch($sandbox, $patterns, $replacements, $dpatterns, $dreplacements, $limit);
1267
1268
  // If less than limit was processed, the update process is finished.
1269
  if ($processed_count < $limit || $sandbox['progress'] == $sandbox['max']) {
1270
    $finished = TRUE;
1271
  }
1272
1273
  // If there's no max value then there's nothing to update and we're finished.
1274
  if (empty($sandbox['max']) || isset($finished)) {
1275
    $message = t('Your existing webforms have been upgraded to use the global Drupal 7 token system.');
1276
    if (!module_exists('token')) {
1277
      $message .= ' <strong>' . t('Please download and install the <a href="http://drupal.org/project/token" target="_blank">Token module</a>. Otherwise some tokens will not be rendered.') . '</strong>';
1278
    }
1279
    return $message;
1280
  }
1281
  else {
1282
    // Indicate our current progress to the batch update system.
1283
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
1284
  }
1285
}
1286
1287
/**
1288
 * Utility function to update all the locations that use tokens.
1289
 */
1290
function _webform_update_7401_batch(&$sandbox, $patterns, $replacements, $dpatterns, $dreplacements, $limit) {
1291
  // Set up the initial batch process.
1292
  if (!isset($sandbox['progress'])) {
1293
    $sandbox['progress'] = 0;
1294
    $sandbox['last_nid_processed'] = -1;
1295
    $sandbox['max'] = db_select('webform')
1296
      ->countQuery()
1297
      ->execute()
1298
      ->fetchField();
1299
1300
    // Update tokens in variables.
1301
    $variables = array(
1302
      'webform_default_subject',
1303
      'webform_default_from_name',
1304
      'webform_default_from_address',
1305
    );
1306
    foreach ($variables as $variable) {
1307
      $value = variable_get($variable, NULL);
1308
      if ($value !== NULL) {
1309
        $value = str_replace($patterns, $replacements, $value);
1310
        $value = preg_replace($dpatterns, $dreplacements, $value);
1311
        variable_set($variable, $value);
1312
      }
1313
    }
1314
  }
1315
1316
  $webforms = db_select('webform', 'w')
1317
    ->fields('w')
1318
    ->condition('nid', $sandbox['last_nid_processed'], '>')
1319
    ->orderBy('nid', 'ASC')
1320
    ->range(0, $limit)
1321
    ->execute()
1322
    ->fetchAllAssoc('nid', PDO::FETCH_ASSOC);
1323
1324
  foreach ($webforms as $nid => $webform) {
1325
    // Update the webform record itself.
1326
    $original = $webform;
1327
    $parts = array(
1328
      'confirmation',
1329
      'redirect_url',
1330
    );
1331
    foreach ($parts as $part) {
1332
      $webform[$part] = str_replace($patterns, $replacements, $webform[$part]);
1333
      $webform[$part] = preg_replace($dpatterns, $dreplacements, $webform[$part]);
1334
    }
1335
    if ($webform != $original) {
1336
      drupal_write_record('webform', $webform, array('nid'));
1337
    }
1338
1339
    // Update tokens in component configurations.
1340
    $result = db_select('webform_component', 'wc', array('fetch' => PDO::FETCH_ASSOC))
1341
      ->fields('wc')
1342
      ->condition('wc.nid', $nid)
1343
      ->execute();
1344
    foreach ($result as $component) {
1345
      $original_extra = $component['extra'];
1346
      $original_value = $component['value'];
1347
      $component['extra'] = unserialize($component['extra']);
1348
      if (isset($component['extra']['description'])) {
1349
        $description = str_replace($patterns, $replacements, $component['extra']['description']);
1350
        $description = preg_replace($dpatterns, $dreplacements, $description);
1351
        $component['extra']['description'] = $description;
1352
      }
1353
      $component['extra'] = serialize($component['extra']);
1354
      $value = str_replace($patterns, $replacements, $component['value']);
1355
      $value = preg_replace($dpatterns, $dreplacements, $value);
1356
      $component['value'] = $value;
1357
      if ($component['extra'] != $original_extra || $component['value'] != $original_value) {
1358
        drupal_write_record('webform_component', $component, array('nid', 'cid'));
1359
      }
1360
    }
1361
1362
    // Update tokens in e-mail configurations.
1363
    $result = db_select('webform_emails', 'we', array('fetch' => PDO::FETCH_ASSOC))
1364
      ->fields('we')
1365
      ->condition('we.nid', $nid)
1366
      ->execute();
1367
    foreach ($result as $email) {
1368
      $parts = array(
1369
        'template',
1370
        'subject',
1371
        'from_name',
1372
      );
1373
      $original = $email;
1374
      foreach ($parts as $part) {
1375
        $email[$part] = str_replace($patterns, $replacements, $email[$part]);
1376
        $email[$part] = preg_replace($dpatterns, $dreplacements, $email[$part]);
1377
      }
1378
      if ($email != $original) {
1379
        drupal_write_record('webform_emails', $email, array('nid', 'eid'));
1380
      }
1381
    }
1382
1383
    // Update the last processed NID.
1384
    $sandbox['last_nid_processed'] = $nid;
1385
    $sandbox['progress']++;
1386
  }
1387
  return count($webforms);
1388
}
1389
1390
/**
1391
 * Add the webform_conditional database table.
1392
 */
1393
function webform_update_7402() {
1394
  // Sanity checks.
1395
  if (db_table_exists('webform_conditional')) {
1396
    // Both tables exist, so these are Webform-core provided tables.
1397
    if (db_table_exists('webform_conditional_rules')) {
1398
      return;
1399
    }
1400
    // Webform Conditional module was installed previously but not uninstalled.
1401
    else {
1402
      throw new DrupalUpdateException(t('The "Webform Conditional" module has previously been installed on your site. Either uninstall the module or drop the database table "webform_conditional".'));
1403
    }
1404
  }
1405
1406
  $schema['webform_conditional'] = array(
1407
    'description' => 'Holds information about conditional logic.',
1408
    'fields' => array(
1409
      'nid' => array(
1410
        'description' => 'The node identifier of a webform.',
1411
        'type' => 'int',
1412
        'unsigned' => TRUE,
1413
        'not null' => TRUE,
1414
        'default' => 0,
1415
      ),
1416
      'rgid' => array(
1417
        'description' => 'The rule group identifier for this group of rules.',
1418
        'type' => 'int',
1419
        'size' => 'small',
1420
        'unsigned' => TRUE,
1421
        'not null' => TRUE,
1422
        'default' => 0,
1423
      ),
1424
      'andor' => array(
1425
        'description' => 'Whether to AND or OR the actions in this group. All actions within the same crid should have the same andor value.',
1426
        'type' => 'varchar',
1427
        'length' => 128,
1428
      ),
1429
      'action' => array(
1430
        'description' => 'The action to be performed on the target. Typically "show" or "hide" for targets of type "component", and "send" for targets of type "email".',
1431
        'type' => 'varchar',
1432
        'length' => 128,
1433
      ),
1434
      'target_type' => array(
1435
        'description' => 'The type of target to be affected. Either "component" or "email". Indicates what type of ID the "target" column contains.',
1436
        'type' => 'varchar',
1437
        'length' => 128,
1438
      ),
1439
      'target' => array(
1440
        'description' => 'The ID of the target to be affected. Typically a component ID.',
1441
        'type' => 'varchar',
1442
        'length' => 128,
1443
      ),
1444
      'weight' => array(
1445
        'description' => 'Determines the position of this conditional compared to others.',
1446
        'type' => 'int',
1447
        'size' => 'small',
1448
        'not null' => TRUE,
1449
        'default' => 0,
1450
      ),
1451
    ),
1452
    'primary key' => array('nid', 'rgid'),
1453
  );
1454
1455
  $schema['webform_conditional_rules'] = array(
1456
    'description' => 'Holds information about conditional logic.',
1457
    'fields' => array(
1458
      'nid' => array(
1459
        'description' => 'The node identifier of a webform.',
1460
        'type' => 'int',
1461
        'unsigned' => TRUE,
1462
        'not null' => TRUE,
1463
        'default' => 0,
1464
      ),
1465
      'rgid' => array(
1466
        'description' => 'The rule group identifier for this group of rules.',
1467
        'type' => 'int',
1468
        'size' => 'small',
1469
        'unsigned' => TRUE,
1470
        'not null' => TRUE,
1471
        'default' => 0,
1472
      ),
1473
      'rid' => array(
1474
        'description' => 'The rule identifier for this conditional rule.',
1475
        'type' => 'int',
1476
        'size' => 'small',
1477
        'unsigned' => TRUE,
1478
        'not null' => TRUE,
1479
        'default' => 0,
1480
      ),
1481
      'source_type' => array(
1482
        'description' => 'The type of source on which the conditional is based. Currently always "component". Indicates what type of ID the "source" column contains.',
1483
        'type' => 'varchar',
1484
        'length' => 128,
1485
      ),
1486
      'source' => array(
1487
        'description' => 'The component ID being used in this condition.',
1488
        'type' => 'int',
1489
        'size' => 'small',
1490
        'unsigned' => TRUE,
1491
        'not null' => TRUE,
1492
        'default' => 0,
1493
      ),
1494
      'operator' => array(
1495
        'description' => 'Which operator (equal, contains, starts with, etc.) should be used for this comparison between the source and value?',
1496
        'type' => 'varchar',
1497
        'length' => 128,
1498
      ),
1499
      'value' => array(
1500
        'description' => 'The value to be compared with source.',
1501
        'type' => 'text',
1502
      ),
1503
    ),
1504
    'primary key' => array('nid', 'rgid', 'rid'),
1505
  );
1506
1507
  db_create_table('webform_conditional', $schema['webform_conditional']);
1508
  db_create_table('webform_conditional_rules', $schema['webform_conditional_rules']);
1509
  // Rebuild schema so that webform_update_7403() can use drupal_write_record().
1510
  if (db_table_exists('system') && db_field_exists('system', 'status')) {
1511
    drupal_get_schema(NULL, TRUE);
1512
  }
1513
}
1514
1515
/**
1516
 * Convert per-component conditionals to new more flexible conditional system.
1517
 */
1518
function webform_update_7403(&$sandbox) {
1519
  // Set up the initial batch process.
1520
  if (!isset($sandbox['progress'])) {
1521
    $sandbox['progress'] = 0;
1522
    $sandbox['last_nid_processed'] = -1;
1523
    $sandbox['converted_count'] = 0;
1524
    $sandbox['max'] = db_select('webform')
1525
      ->countQuery()
1526
      ->execute()
1527
      ->fetchField();
1528
  }
1529
1530
  $limit = webform_variable_get('webform_update_batch_size');
1531
  $webforms = db_select('webform', 'w')
1532
    ->fields('w')
1533
    ->condition('nid', $sandbox['last_nid_processed'], '>')
1534
    ->orderBy('nid', 'ASC')
1535
    ->range(0, $limit)
1536
    ->execute()
1537
    ->fetchAllAssoc('nid', PDO::FETCH_ASSOC);
1538
1539
  foreach ($webforms as $nid => $webform) {
1540
    // Update tokens in component configurations.
1541
    $result = db_select('webform_component', 'wc', array('fetch' => PDO::FETCH_ASSOC))
1542
      ->fields('wc')
1543
      ->condition('wc.nid', $nid)
1544
      ->execute();
1545
    $rgid = 0;
1546
    foreach ($result as $component) {
1547
      // For each component, check if it has conditional properties that need
1548
      // to be removed and/or migrated. Because these properties may be in any
1549
      // order, copy the original extra array for comparison.
1550
      $component['extra'] = unserialize($component['extra']);
1551
      $original_extra = $component['extra'];
1552
1553
      // Remove conditional properties if present.
1554
      if (isset($component['extra']['conditional_component'])) {
1555
        unset($component['extra']['conditional_component']);
1556
      }
1557
      if (isset($component['extra']['conditional_operator'])) {
1558
        unset($component['extra']['conditional_operator']);
1559
      }
1560
      if (isset($component['extra']['conditional_values'])) {
1561
        unset($component['extra']['conditional_values']);
1562
1563
        // If the component has conditional values specified, that indicates
1564
        // that this component was conditionally shown. Convert it to a new
1565
        // conditional with multiple rules if needed.
1566
        if (strlen(trim($original_extra['conditional_values'])) && !empty($original_extra['conditional_operator']) && !empty($original_extra['conditional_component'])) {
1567
          $conditional_values = explode("\n", $original_extra['conditional_values']);
1568
          $rules = array();
1569
          $rule = array(
1570
            'nid' => $nid,
1571
            'rgid' => $rgid,
1572
            'rid' => NULL,
1573
            'source_type' => 'component',
1574
            'source' => $original_extra['conditional_component'],
1575
            'operator' => 'equal',
1576
            'value' => NULL,
1577
          );
1578
          foreach ($conditional_values as $value) {
1579
            $value = trim($value);
1580
            if ($value) {
1581
              $new_rule = $rule;
1582
              $new_rule['rid'] = count($rules);
1583
              $new_rule['value'] = $value;
1584
              $rules[] = $new_rule;
1585
            }
1586
          }
1587
          if (count($rules)) {
1588
            $conditional = array(
1589
              'nid' => $nid,
1590
              'rgid' => $rgid,
1591
              'andor' => 'or',
1592
              'action' => ($original_extra['conditional_operator'] === '=') ? 'show' : 'hide',
1593
              'target_type' => 'component',
1594
              'target' => $component['cid'],
1595
              'weight' => 0,
1596
            );
1597
            drupal_write_record('webform_conditional', $conditional);
1598
            foreach ($rules as $rule) {
1599
              drupal_write_record('webform_conditional_rules', $rule);
1600
            }
1601
            $sandbox['converted_count']++;
1602
            $rgid++;
1603
          }
1604
        }
1605
      }
1606
1607
      // Update the component with the conditional properties removed.
1608
      if ($component['extra'] != $original_extra) {
1609
        $component['extra'] = serialize($component['extra']);
1610
        drupal_write_record('webform_component', $component, array('nid', 'cid'));
1611
      }
1612
    }
1613
1614
    // Update the last processed NID.
1615
    $sandbox['last_nid_processed'] = $nid;
1616
    $sandbox['progress']++;
1617
  }
1618
1619
  // If less than limit was processed, the update process is finished.
1620
  if (count($webforms) < $limit || $sandbox['progress'] == $sandbox['max']) {
1621
    $finished = TRUE;
1622
  }
1623
1624
  // If there's no max value then there's nothing to update and we're finished.
1625
  if (empty($sandbox['max']) || isset($finished)) {
1626
    return t('@count webforms using conditionals updated to the new conditional system.', array('@count' => $sandbox['converted_count']));
1627
  }
1628
  else {
1629
    // Indicate our current progress to the batch update system.
1630
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
1631
  }
1632
}
1633
1634
/**
1635
 * Remove files left over from deleted submissions. Such files are now deleted
1636 85ad3d82 Assos Assos
 * automatically.
1637
 */
1638 a45e4bc1 Assos Assos
function webform_update_7404() {
1639 85ad3d82 Assos Assos
  module_load_include('inc', 'webform', 'components/file');
1640 a45e4bc1 Assos Assos
  $fids = db_query('SELECT fid FROM {file_usage} WHERE module = \'webform\' AND type = \'submission\' AND NOT id IN(SELECT sid FROM {webform_submissions})')->fetchCol();
1641 85ad3d82 Assos Assos
  foreach ($fids as $fid) {
1642
    _webform_delete_file(NULL, array($fid));
1643
  }
1644
}
1645 c22e192e Assos Assos
1646
/**
1647 a45e4bc1 Assos Assos
 * Add an "extra" column to the e-mail table for for non-queryable options.
1648 c22e192e Assos Assos
 */
1649 a45e4bc1 Assos Assos
function webform_update_7405() {
1650
  $schema = array(
1651
    '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.',
1652
    'type' => 'text',
1653
    'not null' => TRUE,
1654
    'initial' => '',
1655
  );
1656
  if (!db_field_exists('webform_emails', 'extra')) {
1657
    db_add_field('webform_emails', 'extra', $schema);
1658
  }
1659
}
1660
1661
/**
1662
 * Convert the "webform_use_cookies" setting to "webform_tracking_mode".
1663
 */
1664
function webform_update_7406() {
1665
  // Previously, we only had "strict" and "ip_address" checking. Using cookies
1666
  // meant cookies in addition to IP address.
1667
  $use_cookies = variable_get('webform_use_cookies');
1668
  if (isset($use_cookies)) {
1669
    variable_set('webform_tracking_mode', $use_cookies ? 'strict' : 'ip_address');
1670
    variable_del('webform_use_cookies');
1671
  }
1672
}
1673
1674
/**
1675
 * Remove orphaned conditional rules.
1676
 */
1677
function webform_update_7407() {
1678
  // Delete entire conditions for deleted components that were the target.
1679
  // This query is complicated by database compatibility since we're joining two
1680
  // non-matching columns. See http://drupal.org/node/2026891.
1681
  $result = db_query("SELECT rg.* FROM {webform_conditional} rg LEFT JOIN {webform_component} c ON rg.nid = c.nid AND rg.target_type = 'component' AND rg.target = RTRIM(CAST(c.cid AS CHAR(10))) WHERE c.cid IS NULL");
1682
  foreach ($result as $row) {
1683
    db_delete('webform_conditional')
1684
      ->condition('nid', $row->nid)
1685
      ->condition('rgid', $row->rgid)
1686
      ->execute();
1687
    db_delete('webform_conditional_rules')
1688
      ->condition('nid', $row->nid)
1689
      ->condition('rgid', $row->rgid)
1690
      ->execute();
1691
  }
1692
  // Delete conditional rules for deleted components that were the source.
1693
  $result = db_query("SELECT r.* FROM {webform_conditional_rules} r LEFT JOIN {webform_component} c ON r.nid = c.nid AND r.source_type = 'component' AND r.source = c.cid WHERE c.cid IS NULL");
1694
  foreach ($result as $row) {
1695
    db_delete('webform_conditional_rules')
1696
      ->condition('nid', $row->nid)
1697
      ->condition('rgid', $row->rgid)
1698
      ->condition('rid', $row->rid)
1699
      ->execute();
1700
  }
1701
  // Delete any conditions that no longer have any rules left in them.
1702
  $result = db_query("SELECT rg.* FROM {webform_conditional} rg LEFT JOIN {webform_conditional_rules} r ON rg.nid = r.nid AND rg.rgid = r.rgid WHERE r.rgid IS NULL");
1703
  foreach ($result as $row) {
1704
    db_delete('webform_conditional')
1705
      ->condition('nid', $row->nid)
1706
      ->condition('rgid', $row->rgid)
1707
      ->execute();
1708
  }
1709
}
1710
1711
/**
1712
 * Rename the "mandatory" column to "required".
1713
 */
1714
function webform_update_7408() {
1715
  $spec = array(
1716
    'description' => 'Boolean flag for if this component is required.',
1717
    'type' => 'int',
1718
    'size' => 'tiny',
1719
    'not null' => TRUE,
1720
    'default' => 0,
1721
  );
1722
  if (!db_field_exists('webform_component', 'required')) {
1723
    db_change_field('webform_component', 'mandatory', 'required', $spec);
1724
  }
1725
}
1726
1727
/**
1728
 * Add progress bar columns to the webform table.
1729
 */
1730
function webform_update_7409() {
1731
  if (!db_field_exists('webform', 'progressbar_bar')) {
1732
    $int_schema = array(
1733
      'type' => 'int',
1734
      'size' => 'tiny',
1735
      'not null' => TRUE,
1736
      'default' => 0,
1737
    );
1738
    $varchar_schema = array(
1739
      'type' => 'varchar',
1740
      'length' => 255,
1741
    );
1742
1743
    $int_schema['description'] = 'Boolean value indicating if the bar should be shown as part of the progress bar.';
1744
    db_add_field('webform', 'progressbar_bar', $int_schema);
1745
1746
    $int_schema['description'] = 'Boolean value indicating if the page number should be shown as part of the progress bar.';
1747
    db_add_field('webform', 'progressbar_page_number', $int_schema);
1748
1749
    $int_schema['description'] = 'Boolean value indicating if the percentage complete should be shown as part of the progress bar.';
1750
    db_add_field('webform', 'progressbar_percent', $int_schema);
1751
1752
    $int_schema['description'] = 'Boolean value indicating if the pagebreak labels should be included as part of the progress bar.';
1753
    db_add_field('webform', 'progressbar_pagebreak_labels', $int_schema);
1754
1755
    $int_schema['description'] = 'Boolean value indicating if the confirmation page should count as a page in the progress bar.';
1756
    db_add_field('webform', 'progressbar_include_confirmation', $int_schema);
1757
1758
    $varchar_schema['description'] = 'Label for the first page of the progress bar.';
1759
    db_add_field('webform', 'progressbar_label_first', $varchar_schema);
1760
1761
    $varchar_schema['description'] = 'Label for the last page of the progress bar.';
1762
    db_add_field('webform', 'progressbar_label_confirmation', $varchar_schema);
1763
1764
    return t('New webform columns added.');
1765
  }
1766
}
1767
1768
/**
1769
 * Remove the "teaser" column from the "webform" table.
1770
 */
1771
function webform_update_7410() {
1772
  if (db_field_exists('webform', 'teaser')) {
1773
    db_drop_field('webform', 'teaser');
1774
    return t('Removed "teaser" column. All forms that had the "Show complete form in teaser" option disabled will now show forms in their teasers. Use view modes to hide the form if desired.');
1775
  }
1776
}
1777
1778
/**
1779
 * Remove [submission:values:x] token use of :nolabel and add :withlabel.
1780
 */
1781
function webform_update_7411(&$sandbox) {
1782
  // Define replacements.
1783
  $patterns = array();
1784
  $replacements = array();
1785
  $dpatterns = array(
1786
    '/\[submission:values(:(?!nolabel)[a-z_]+)+\]/m',
1787
    '/\[submission:values(:([a-z_:]+))?:nolabel\]/m',
1788
  );
1789
  $dreplacements = array(
1790
    '[submission:values$1:withlabel]',
1791
    '[submission:values$1]',
1792
  );
1793
1794
  $limit = webform_variable_get('webform_update_batch_size');
1795
  $processed_count = _webform_update_7401_batch($sandbox, $patterns, $replacements, $dpatterns, $dreplacements, $limit);
1796
1797
  // If less than limit was processed, the update process is finished.
1798
  if ($processed_count < $limit || $sandbox['progress'] == $sandbox['max']) {
1799
    $finished = TRUE;
1800
  }
1801
1802
  // If there's no max value then there's nothing to update and we're finished.
1803
  if (empty($sandbox['max']) || isset($finished)) {
1804
    return t('Replaced tokens using [submission:values:x] with [submission:values:x:withlabel].');
1805
  }
1806
  else {
1807
    // Indicate our current progress to the batch update system.
1808
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
1809
  }
1810
}
1811
1812
/**
1813
 * Split webform_node_types as content type specific.
1814
 */
1815
function webform_update_7412() {
1816
  $types = variable_get('webform_node_types', array('webform'));
1817
  foreach ($types as $type) {
1818
    variable_set('webform_node_' . $type, TRUE);
1819
  }
1820
  variable_del('webform_node_types');
1821
}
1822
1823
/**
1824
 * Add preview page columns to the webform table.
1825
 */
1826
function webform_update_7413() {
1827
  if (!db_field_exists('webform', 'preview')) {
1828
    $int_schema = array(
1829
      'type' => 'int',
1830
      'size' => 'tiny',
1831
      'not null' => TRUE,
1832
      'default' => 0,
1833
    );
1834
    $varchar_schema = array(
1835
      'type' => 'varchar',
1836
      'length' => 255,
1837
    );
1838
    $text_schema = array(
1839
      'type' => 'text',
1840
      'not null' => TRUE,
1841
      'initial' => '',
1842
    );
1843
1844
    $int_schema['description'] = 'Boolean value indicating if this form includes a page for previewing the submission.';
1845
    db_add_field('webform', 'preview', $int_schema);
1846
1847
    $varchar_schema['description'] = 'The text for the button that will proceed to the preview page.';
1848
    db_add_field('webform', 'preview_next_button_label', $varchar_schema);
1849
1850
    $varchar_schema['description'] = 'The text for the button to go backwards from the preview page.';
1851
    db_add_field('webform', 'preview_prev_button_label', $varchar_schema);
1852
1853
    $varchar_schema['description'] = 'The title of the preview page, as used by the progress bar.';
1854
    db_add_field('webform', 'preview_title', $varchar_schema);
1855
1856
    $text_schema['description'] = 'Text shown on the preview page of the form.';
1857
    db_add_field('webform', 'preview_message', $text_schema);
1858
1859
    $varchar_schema['description'] = 'The {filter_format}.format of the preview page message.';
1860
    db_add_field('webform', 'preview_message_format', $varchar_schema);
1861
1862
    $text_schema['description'] = 'Comma-separated list of component IDs that should not be included in this form\'s confirmation page.';
1863
    db_add_field('webform', 'preview_excluded_components', $text_schema);
1864
1865
    return t('New webform columns added.');
1866
  }
1867
}
1868
1869
/**
1870
 * Change email subject, from_name and from_address fields to type 'TEXT'.
1871
 */
1872
function webform_update_7414() {
1873
  $schema = array(
1874
    'subject' => array(
1875
      'description' => 'The e-mail subject that will be used. This may be a string, the special key "default" or a numeric value. If a numeric value is used, the value of a component will be substituted on submission.',
1876
      'type' => 'text',
1877
      'not null' => FALSE,
1878
    ),
1879
    'from_name' => array(
1880
      'description' => 'The e-mail "from" name that will be used. This may be a string, the special key "default" or a numeric value. If a numeric value is used, the value of a component will be substituted on submission.',
1881
      'type' => 'text',
1882
      'not null' => FALSE,
1883
    ),
1884
    'from_address' => array(
1885
      'description' => 'The e-mail "from" e-mail address that will be used. This may be a string, the special key "default" or a numeric value. If a numeric value is used, the value of a component will be substituted on submission.',
1886
      'type' => 'text',
1887
      'not null' => FALSE,
1888
    ),
1889
  );
1890
1891
  db_change_field('webform_emails', 'subject', 'subject', $schema['subject']);
1892
  db_change_field('webform_emails', 'from_name', 'from_name', $schema['from_name']);
1893
  db_change_field('webform_emails', 'from_address', 'from_address', $schema['from_address']);
1894
1895
  return t('Custom email columns successfully changed.');
1896
}
1897
1898
/**
1899
 * Increase length of webform.redirect_url.
1900
 */
1901
function webform_update_7415() {
1902
  $spec = array(
1903
    'description' => 'The URL a user is redirected to after submitting a form.',
1904
    'type' => 'varchar',
1905
    'length' => 2048,
1906
    'default' => '<confirmation>',
1907
  );
1908
  db_change_field('webform', 'redirect_url', 'redirect_url', $spec);
1909
}
1910
1911
/**
1912
 * Add columns for serial numbered submissions. Add serial numbers to existing submissions.
1913
 */
1914
function webform_update_7416() {
1915
  // SQL database implementations vary in how DDL statements are handled within
1916
  // transactions. Since this update routine should be run in maintenance mode
1917
  // without concurrent transactions, no DDL statements are executed within a
1918
  // transaction.
1919
1920
  // Add next_serial column to webform.
1921
  $spec = array(
1922
    'description' => 'The serial number to give to the next submission to this webform.',
1923
    'type' => 'int',
1924
    'unsigned' => TRUE,
1925
    'not null' => TRUE,
1926
    'default' => 1,
1927
  );
1928
  if (!db_field_exists('webform', 'next_serial')) {
1929
    db_add_field('webform', 'next_serial', $spec);
1930
  }
1931
1932
  // Add serial column to webform_submissions.
1933
  $spec = array(
1934
    'description' => 'The serial number of this submission.',
1935
    'type' => 'int',
1936
    'unsigned' => TRUE,
1937
  );
1938
  if (!db_field_exists('webform_submissions', 'serial')) {
1939
    db_add_field('webform_submissions', 'serial', $spec);
1940
  }
1941
1942
  // Begin a transaction for updating the serial numbers. The transaction will
1943
  // commit when $txn is unset or goesout-of-scope.
1944
  $txn = db_transaction();
1945
1946
  // Delete stray entries from the Webform tables before adding serial numbers.
1947
  db_query("DELETE FROM {webform_submissions} WHERE nid NOT IN (SELECT nid FROM {webform})");
1948
  db_query("DELETE FROM {webform_submitted_data} WHERE nid NOT IN (SELECT nid FROM {webform})");
1949
1950
1951
  // Add serial numbers to all submissions.
1952
1953
  // Repeat for every Webform.
1954
  $nids = db_select('webform', 'w')
1955
    ->fields('w', array('nid'))
1956
    ->execute();
1957
  while ($nid = $nids->fetchColumn()) {
1958
    $serial = 1;
1959
    // Repeat for every submission in this Webform.
1960
    $sids = db_select('webform_submissions', 'ws')
1961
      ->forUpdate()
1962
      ->fields('ws', array('sid'))
1963
      ->condition('nid', $nid)
1964
      ->orderBy('sid')
1965
      ->execute();
1966
    while ($sid = $sids->fetchColumn()) {
1967
      // Set the serial number.
1968
      db_update('webform_submissions')
1969
        ->fields(array('serial' => $serial))
1970
        ->condition('nid', $nid)
1971
        ->condition('sid', $sid)
1972
        ->execute();
1973
      $serial++;
1974
    }
1975
    // Set the next serial number.
1976
    db_update('webform')
1977
      ->fields(array('next_serial' => $serial))
1978
      ->condition('nid', $nid)
1979
      ->execute();
1980
  }
1981
  // Commit the transaction
1982
  unset($txn);
1983
1984
  // Now that every submission has a serial number, make serial numbers required.
1985
  $spec['not null'] = TRUE;
1986
  $keys = array();
1987
  // Create a unique index if it does not already exist.
1988
  if (!db_index_exists('webform_submissions', 'nid_serial')) {
1989
    $keys = array(
1990
      'unique keys' => array(
1991
        'nid_serial' => array('nid', 'serial'),
1992
      ),
1993
    );
1994
  }
1995
  db_change_field('webform_submissions', 'serial', 'serial', $spec, $keys);
1996
1997
  return t('Columns for serial numbered submissions successfully added. Serial numbers added to existing submissions.');
1998
}
1999
2000
/**
2001
 * Change webform_component.name to text to allow for longer labels.
2002
 */
2003
function webform_update_7417() {
2004 ba09eb79 Assos Assos
  // This update function was introduced in 7.x-4.0rc1, which was the first
2005
  // release to require views. While the views requirement was added to the
2006
  // .info file, and while subsequently hook_requirements() added a check for
2007
  // views, it is possible to arrive at this update function via drush updatedb
2008
  // without views enabled.
2009
  $result = NULL;
2010
  if (!module_exists('views')) {
2011
    if (module_enable(array('views'))) {
2012
      $result = t('The Views module was automatically enabled.');
2013
    }
2014
    else {
2015
      throw new DrupalUpdateException(t('UPDATE ERROR: The Views module must be downloaded and enabled before Webform updates can proceed.'));
2016
    }
2017
  }
2018
2019 a45e4bc1 Assos Assos
  db_change_field('webform_component', 'name', 'name', array('type' => 'text', 'not null' => TRUE));
2020 ba09eb79 Assos Assos
  return $result;
2021 a45e4bc1 Assos Assos
}
2022
2023
/**
2024
 * Upgrade the "extra" column in the e-mail table to be consistent with a new
2025
 * webform installation.
2026
 *
2027
 * In version 7.x-4.0-rc6 and earlier, the extra field was added with 'not null'
2028
 * FALSE, cause the schema module to report in mismatch. While functionally this
2029
 * causes no problem, this update removes the schema module's warning.
2030
 */
2031
function webform_update_7418() {
2032
  // While there should never be any NULL values in the extra field, change them to '' to be safe.
2033
  db_update('webform_emails')
2034
    ->fields(array('extra' => ''))
2035
    ->isNull('extra')
2036
    ->execute();
2037
  // Pass a complete field specification to db_change_field for cross-database compatiblity.
2038
  $spec = array(
2039
    '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.',
2040
    'type' => 'text',
2041
    'not null' => TRUE,
2042
  );
2043
  db_change_field('webform_emails', 'extra', 'extra', $spec);
2044
}
2045
2046
/**
2047
 * Add an index on submitted data.
2048
 */
2049
function webform_update_7419() {
2050
  // Note: MS SQL Server does not support size-limited indexes and the column
2051
  // type (text) is too big to fit inside index size limits.
2052
  if (!db_index_exists('webform_submitted_data', 'data') && db_driver() != 'sqlsrv') {
2053
    db_add_index('webform_submitted_data', 'data', array(array('data', 64)));
2054
  }
2055
}
2056
2057
/**
2058
 * Extend access to the WEBFORM tab to anyone who can access the node's EDIT tab.
2059
 */
2060
function webform_update_7420() {
2061
  user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('edit webform components'));
2062
}
2063
2064
/**
2065
 * Set the administrator option for an HTML-capable mail system to the current automatically-detected option.
2066
 */
2067
function webform_update_7421() {
2068
  $capable = array_reduce(array('mandrill', 'mimemail', 'htmlmail'),
2069
                          function($carry, $module) { return $carry || module_exists($module); },
2070
                          FALSE);
2071
  variable_set('webform_email_html_capable', $capable);
2072
  return $capable
2073
            ? t('An HTML-capable module is installed. The option to send HTML e-mail is enabled.')
2074
            : t('No commonly-known HTML capable module is installed. The option to send HTML e-mail is disabled.');
2075
}
2076
2077
/**
2078
 * Remove the administrator option "Include webform forms in search index" and rely on the Search Index view mode instead.
2079
 */
2080
function webform_update_7422() {
2081
  variable_del('webform_search_index');
2082
  return module_exists('search')
2083
          ? t('Webform forms will now be included in the search index only if the Webform "field" is displayed in the "Search index" view mode.')
2084
          : NULL;
2085
}
2086
2087
/**
2088
 * 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.
2089
 */
2090
function webform_update_7423() {
2091
  // Create webform_condtional_actions table.
2092
  // The table might already exist if this update previously timed-out
2093
  if (!db_table_exists('webform_conditional_actions')) {
2094
    $schema['webform_conditional_actions'] = array(
2095
      'description' => 'Holds information about conditional actions.',
2096
      'fields' => array(
2097
        'nid' => array(
2098
          'description' => 'The node identifier of a webform.',
2099
          'type' => 'int',
2100
          'unsigned' => TRUE,
2101
          'not null' => TRUE,
2102
          'default' => 0,
2103
        ),
2104
        'rgid' => array(
2105
          'description' => 'The rule group identifier for this group of rules.',
2106
          'type' => 'int',
2107
          'size' => 'small',
2108
          'unsigned' => TRUE,
2109
          'not null' => TRUE,
2110
          'default' => 0,
2111
        ),
2112
        'aid' => array(
2113
          'description' => 'The rule identifier for this conditional action.',
2114
          'type' => 'int',
2115
          'size' => 'small',
2116
          'unsigned' => TRUE,
2117
          'not null' => TRUE,
2118
          'default' => 0,
2119
        ),
2120
        'target_type' => array(
2121
          'description' => 'The type of target to be affected. Currently always "component". Indicates what type of ID the "target" column contains.',
2122
          'type' => 'varchar',
2123
          'length' => 128,
2124
        ),
2125
        'target' => array(
2126
          'description' => 'The ID of the target to be affected. Typically a component ID.',
2127
          'type' => 'varchar',
2128
          'length' => 128,
2129
        ),
2130
        'invert' => array(
2131
          'description' => 'If inverted, execute when rule(s) are false.',
2132
          'type' => 'int',
2133
          'size' => 'small',
2134
          'unsigned' => TRUE,
2135
          'not null' => TRUE,
2136
          'default' => 0,
2137
        ),
2138
        'action' => array(
2139
          'description' => 'The action to be performed on the target.',
2140
          'type' => 'varchar',
2141
          'length' => 128,
2142
        ),
2143
        'argument' => array(
2144
          'description' => 'Optional argument for action.',
2145
          'type' => 'text',
2146
        ),
2147
      ),
2148
      'primary key' => array('nid', 'rgid', 'aid'),
2149
    );
2150
    db_create_table('webform_conditional_actions', $schema['webform_conditional_actions']);
2151
  }
2152
2153
  // In a site with many, many conditionals, the db_insert may timeout. Start a transaction to ensure atomic action.
2154
  $tx = db_transaction();
2155
  // Copy target information from existing webform_conditional table to new webfrom_condtional_actions table.
2156
  $select = db_select('webform_conditional', 'c')
2157
    ->fields('c', array('nid', 'rgid', 'action', 'target_type', 'target'))
2158
    ->orderBy('nid')->orderBy('rgid');
2159
  $select->addExpression("''", 'argument');
2160
  db_insert('webform_conditional_actions')
2161
    ->from($select)
2162
    ->execute();
2163
2164
  // Commit the insert
2165
  unset($tx);
2166
2167
  // Remove unneeded columns from webform_conditional.
2168
  foreach (array('action', 'target_type', 'target') as $fieldname) {
2169
    if (db_field_exists('webform_conditional', $fieldname)) {
2170
      db_drop_field('webform_conditional', $fieldname);
2171
    }
2172
  }
2173
2174
  // Rebuild the registry because this point release contains a new class: WebformConditionals.
2175
  registry_rebuild();
2176
2177
  return t('Webform database tables were successfully adjusted to allow more than one action for each conditional.');
2178
}
2179
2180
/**
2181
 * Convert conditional actions of "hide" to "isn't shown".
2182
 */
2183
function webform_update_7424() {
2184
  $count = db_update('webform_conditional_actions')
2185
    ->fields(array('action' => 'show', 'invert' => 1))
2186
    ->condition('action', 'hide')
2187
    ->execute();
2188
  return format_plural($count,
2189
                       '1 "hide" conditional converted to "isn\'t" shown.',
2190
                       '@count conditionals converted to "isn\'t" shown.');
2191
}
2192
2193
/**
2194
 * Add "exclude empty" option to emails.
2195
 */
2196
function webform_update_7425() {
2197
  // Add next_serial column to webform.
2198
  $spec = array(
2199
    'description' => 'Determines if the e-mail will include component with an empty value.',
2200
    'type' => 'int',
2201
    'unsigned' => TRUE,
2202
    'size' => 'tiny',
2203
    'not null' => TRUE,
2204
    'default' => 0,
2205
  );
2206
  if (!db_field_exists('webform_emails', 'exclude_empty')) {
2207
    db_add_field('webform_emails', 'exclude_empty', $spec);
2208
  }
2209
2210
  // Clear the views cache since this release use the webform_analysis view.
2211
  cache_clear_all('*', 'cache_views', TRUE);
2212
2213
  return t('Webform e-mails were sucessfully updated to add the option to exclude empty components.');
2214
}
2215
2216
/**
2217
 * Add configuration to continue sending individual e-mails to multiple recipients.
2218
 */
2219
function webform_update_7426() {
2220
  variable_set('webform_email_address_individual', 1);
2221
}
2222
2223
/**
2224
 * Add database columns for submission completed and modified timestamps. Sites with many submissions may wish to use drush to execute this update.
2225
 */
2226
function webform_update_7427() {
2227
  // Create new timestamp columns.
2228
  $specs = array(
2229
    'completed' => array(
2230
      'description' => 'Timestamp when the form was submitted as complete (not draft).',
2231
      'type' => 'int',
2232
      'not null' => TRUE,
2233
      'default' => 0,
2234
    ),
2235
    'modified' => array(
2236
      'description' => 'Timestamp when the form was last saved (complete or draft).',
2237
      'type' => 'int',
2238
      'not null' => TRUE,
2239
      'default' => 0,
2240
    ),
2241
  );
2242
  foreach ($specs as $field_name => $spec) {
2243
    if (!db_field_exists('webform_submissions', $field_name)) {
2244
      db_add_field('webform_submissions', $field_name, $spec);
2245
    }
2246
  }
2247
2248
  // In a site with many submissions, the db_update may timeout. Start a transaction to ensure atomic action.
2249
  $tx = db_transaction();
2250
  // Copy submitted to completed for non-draft submissions.
2251
  db_update('webform_submissions')
2252
    ->expression('completed', 'submitted')
2253
    ->condition('is_draft', 0)
2254
    ->execute();
2255
  // Commit the update.
2256
  unset($tx);
2257
2258
  // Start another transaction.
2259
  $tx = db_transaction();
2260
  db_update('webform_submissions')
2261
    ->expression('modified', 'submitted')
2262
    ->execute();
2263
  // Commit the update.
2264
  unset($tx);
2265
2266
  // Clear the views cache since to see the completed and modified views fields.
2267
  cache_clear_all('*', 'cache_views', TRUE);
2268
2269
  return t('Webform submissions were updated with completed and modified timestamps.');
2270
}
2271
2272
/**
2273
 * Add a "confidential" option to webforms.
2274
 */
2275
function webform_update_7428() {
2276
  // Add confidential column to webform.
2277
  if (!db_field_exists('webform', 'confidential')) {
2278
    $spec = array(
2279
      'description' => 'Boolean value for whether to anonymize submissions.',
2280
      'type' => 'int',
2281
      'size' => 'tiny',
2282
      'not null' => TRUE,
2283
      'default' => 0,
2284
    );
2285
    db_add_field('webform', 'confidential', $spec);
2286
  }
2287
2288
  return t('Webforms may now be configured to anonymize confidential submissions.');
2289
}
2290
2291
/**
2292
 * 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'.
2293
 */
2294
function webform_update_7429() {
2295
  // Add highest_valid_page column to webform_submissions.
2296
  if (!db_field_exists('webform_submissions', 'highest_valid_page')) {
2297
    $spec = array(
2298
      'description' => 'For drafts, the highest validated page number.',
2299
      'type' => 'int',
2300
      'size' => 'small',
2301
      'not null' => TRUE,
2302
      'default' => 0,
2303
    );
2304
    db_add_field('webform_submissions', 'highest_valid_page', $spec);
2305
  }
2306
2307
  return t('Webforms will now resume draft submissions on the page where the submitter left off.');
2308
}
2309
2310
/**
2311
 * Add a column to the emails table to allow disabling.
2312
 */
2313
function webform_update_7430() {
2314
  // Add status column to webform_emails.
2315
  if (!db_field_exists('webform_emails', 'status')) {
2316
    $spec = array(
2317
      'description' => 'Whether this email is enabled.',
2318
      'type' => 'int',
2319
      'unsigned' => TRUE,
2320
      'size' => 'tiny',
2321
      'not null' => TRUE,
2322
      'default' => 1,
2323
    );
2324
    db_add_field('webform_emails', 'status', $spec);
2325
  }
2326
2327
  return t('Webform emails may now be disabled.');
2328 c22e192e Assos Assos
}