Projet

Général

Profil

Paste
Télécharger (81,3 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / webform / webform.install @ 01f36513

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file
5 feca1e4a Assos Assos
 * Webform module install/schema hooks.
6 85ad3d82 Assos Assos
 */
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 feca1e4a Assos Assos
        '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 85ad3d82 Assos Assos
      ),
61
      'allow_draft' => array(
62 feca1e4a Assos Assos
        '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 85ad3d82 Assos Assos
      ),
68
      'auto_save' => array(
69 feca1e4a Assos Assos
        '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 85ad3d82 Assos Assos
      ),
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 feca1e4a Assos Assos
        'description' => 'Is this a draft of the submission?',
558
        'type' => 'int',
559
        'size' => 'tiny',
560
        'not null' => TRUE,
561
        'default' => 0,
562 85ad3d82 Assos Assos
      ),
563 a45e4bc1 Assos Assos
      'highest_valid_page' => array(
564 feca1e4a Assos Assos
        'description' => 'For drafts, the highest validated page number.',
565
        'type' => 'int',
566
        'size' => 'small',
567
        'not null' => TRUE,
568
        'default' => 0,
569 a45e4bc1 Assos Assos
      ),
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 feca1e4a Assos Assos
    'description' => 'Stores last submission number per user download.',
654 85ad3d82 Assos Assos
    '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 feca1e4a Assos Assos
        'description' => 'The user identifier.',
664 85ad3d82 Assos Assos
        'type' => 'int',
665
        'unsigned' => TRUE,
666
        'not null' => TRUE,
667
        'default' => 0,
668
      ),
669 feca1e4a Assos Assos
      'sid' => array(
670 85ad3d82 Assos Assos
        'description' => 'The last downloaded submission number.',
671
        'type' => 'int',
672
        'unsigned' => TRUE,
673
        'not null' => TRUE,
674
        'default' => 0,
675
      ),
676 feca1e4a Assos Assos
      'requested' => array(
677 85ad3d82 Assos Assos
        '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
 * Implements hook_requirements().
692
 */
693
function webform_requirements($phase) {
694
  $requirements = array();
695
  $t = get_t();
696
697
  // Ensure cURL exists if SimpleTest hasn't checked it already.
698
  if (!class_exists('ZipArchive')) {
699
    $requirements['webform_zip'] = array(
700
      'title' => $t('Zip archive support'),
701
      'value' => $t('Missing'),
702 feca1e4a Assos Assos
      'severity' => REQUIREMENT_INFO,
703 a45e4bc1 Assos Assos
      'description' => $t('PHP does not have the zip archive extension available. Webform module requires zip support for exporting submissions to Microsoft Excel.'),
704
    );
705
  }
706
  // Though the .info file specifies PHP version as well, this will prevent
707
  // users from upgrading from 3.x if their PHP version is too old.
708
  if (version_compare(phpversion(), '5.3') < 0) {
709
    $requirements['webform_php'] = array(
710 ba09eb79 Assos Assos
      'title' => $t('Webform PHP requirement'),
711 a45e4bc1 Assos Assos
      'value' => phpversion(),
712
      'severity' => REQUIREMENT_ERROR,
713
      'description' => $t('Webform requires PHP 5.3 or higher.'),
714
    );
715
  }
716 ba09eb79 Assos Assos
  // Ensure that views is enabled as it is a new .info requirement starting
717
  // with version 7.x-4.0rc1. On installation, the .info file is sufficient to
718
  // cause the dependencies to be installed. On update, update.php will
719
  // respect this hook_requirements implementation, but as of drush 6.3.0 and
720
  // drush 7.0.0, drush updatedb will not. See:
721
  // https://github.com/drush-ops/drush/issues/1427
722
  if ($phase != 'install' && !module_exists('views')) {
723
    $requirements['webform_views'] = array(
724
      'title' => $t('Webform Views requirement'),
725
      'value' => $t('Missing'),
726
      'severity' => REQUIREMENT_ERROR,
727
      'description' => $t('Webform requires Views, which is not installed and enabled.'),
728
    );
729
  }
730 a45e4bc1 Assos Assos
731
  return $requirements;
732
}
733
734 85ad3d82 Assos Assos
/**
735
 * Implements hook_install().
736
 */
737
function webform_install() {
738
  module_load_include('inc', 'node', 'content_types');
739
  db_update('system')
740
    ->condition('name', 'webform')
741
    ->condition('type', 'module')
742
    ->fields(array('weight' => -1))
743
    ->execute();
744
745
  // Optionally create the default webform type.
746
  if (variable_get('webform_install_create_content_type', TRUE)) {
747
    $webform_type = array(
748
      'type' => 'webform',
749
      'name' => st('Webform'),
750
      'base' => 'node_content',
751
      'description' => st('Create a new form or questionnaire accessible to users. Submission results and statistics are recorded and accessible to privileged users.'),
752
      'custom' => TRUE,
753
      'modified' => TRUE,
754
      'locked' => FALSE,
755
    );
756
    $webform_type = node_type_set_defaults($webform_type);
757
    node_type_save($webform_type);
758 a45e4bc1 Assos Assos
    // Enable webform components by default on Webform nodes.
759
    variable_set('webform_node_webform', TRUE);
760
    // Now that a webform node type has been created, reset the cache of the
761
    // node types that support webforms. This is needed for tests which will
762
    // create nodes in the same execution.
763
    drupal_static_reset('webform_node_types');
764
    if (variable_get('webform_install_add_body_field', FALSE)) {
765 3753f249 Assos Assos
      node_add_body_field($webform_type);
766
    }
767 a45e4bc1 Assos Assos
    // Disable comments by default on Webform nodes.
768
    variable_set('comment_webform', '0');
769
  }
770
  else {
771
    variable_set('webform_node_types_primary', array());
772
  }
773
774
  // Note: MS SQL Server does not support size-limited indexes and the column
775
  // type (text) is too big to fit inside index size limits.
776
  if (!db_index_exists('webform_submitted_data', 'data') && db_driver() != 'sqlsrv') {
777
    db_add_index('webform_submitted_data', 'data', array(array('data', 64)));
778 85ad3d82 Assos Assos
  }
779
}
780
781
/**
782
 * Implements hook_uninstall().
783
 */
784
function webform_uninstall() {
785
  // Unset webform variables.
786 a45e4bc1 Assos Assos
  variable_del('webform_blocks');
787
  variable_del('webform_tracking_mode');
788
  variable_del('webform_allowed_tags');
789
  variable_del('webform_email_address_format');
790
  variable_del('webform_email_address_individual');
791 85ad3d82 Assos Assos
  variable_del('webform_default_from_name');
792 a45e4bc1 Assos Assos
  variable_del('webform_default_from_address');
793 85ad3d82 Assos Assos
  variable_del('webform_default_subject');
794 a45e4bc1 Assos Assos
  variable_del('webform_email_replyto');
795
  variable_del('webform_email_html_capable');
796 85ad3d82 Assos Assos
  variable_del('webform_default_format');
797
  variable_del('webform_format_override');
798 a45e4bc1 Assos Assos
  variable_del('webform_email_select_max');
799
  variable_del('webform_node_types_primary');
800
  variable_del('webform_date_type');
801 3753f249 Assos Assos
  variable_del('webform_export_format');
802 a45e4bc1 Assos Assos
  variable_del('webform_csv_delimiter');
803 01d522a6 Assos Assos
  variable_del('webform_csv_line_ending');
804 a45e4bc1 Assos Assos
  variable_del('webform_export_wordwrap');
805
  variable_del('webform_excel_legacy_exporter');
806
  variable_del('webform_progressbar_style');
807
  variable_del('webform_progressbar_label_first');
808
  variable_del('webform_progressbar_label_confirmation');
809
  variable_del('webform_table');
810 3753f249 Assos Assos
  variable_del('webform_submission_access_control');
811 ba09eb79 Assos Assos
  variable_del('webform_token_access');
812 3753f249 Assos Assos
  variable_del('webform_update_batch_size');
813 a45e4bc1 Assos Assos
  variable_del('webform_disabled_components');
814
815
  foreach (node_type_get_names() as $type => $name) {
816
    variable_del('webform_node_' . $type);
817
  }
818 85ad3d82 Assos Assos
819
  $component_list = array();
820
  $path = drupal_get_path('module', 'webform') . '/components';
821
  $files = file_scan_directory($path, '/^.*\.inc$/');
822
  foreach ($files as $filename => $file) {
823
    variable_del('webform_enable_' . $file->name, 1);
824
  }
825
826
  // Delete uploaded files.
827
  $filepath = file_build_uri('webform');
828
  file_unmanaged_delete_recursive($filepath);
829 a45e4bc1 Assos Assos
830
  // Delete the content type "webform" if:
831
  //   a) there are no existing nodes of type webform and
832
  //   b) no additional fields have been defined for node type webform, beyond
833
  //      the default body field.
834
  $query = new EntityFieldQuery();
835
  $results = $query->entityCondition('entity_type', 'node')
836
    ->entityCondition('bundle', 'webform')
837
    ->range(0, 1)
838
    ->execute();
839
  $instances = field_info_instances('node', 'webform');
840
  unset($instances['body']);
841
  if (!$results && !$instances) {
842
    node_type_delete('webform');
843
    drupal_flush_all_caches();
844
  }
845
846 85ad3d82 Assos Assos
}
847
848 e9984459 Assos Assos
/**
849
 * Implements hook_update_dependencies().
850
 */
851
function webform_update_dependencies() {
852
  // Create the {filter_format} table before trying to use it.
853
  $dependencies['webform'][7301] = array(
854
    'filter' => 7000,
855
  );
856
  // Create the {file_managed} table before trying to use it.
857
  $dependencies['webform'][7319] = array(
858
    'system' => 7034,
859
  );
860
  // Create the {file_usage} table before trying to use it.
861
  $dependencies['webform'][7320] = array(
862
    'system' => 7059,
863
  );
864 01f36513 Assos Assos
  // Ensure rules tables and fields exist before trying to use it.
865
  $dependencies['webform'][7420] = array(
866
    'rules' => 7213,
867
  );
868 e9984459 Assos Assos
  return $dependencies;
869
}
870
871 85ad3d82 Assos Assos
/**
872
 * Set the minimum upgrade version.
873
 *
874
 * Currently you cannot upgrade from 2.x in Drupal 6 to 3.x in Drupal 7. However
875
 * there are no database changes between the 3.x versions, so no update is
876
 * needed at all to move from 3.x in Drupal 6 to Drupal 7.
877
 */
878
function webform_update_last_removed() {
879
  return 6313;
880
}
881
882
/**
883
 * Allow the confirmation format column to have a NULL value.
884
 */
885
function webform_update_7301() {
886
  // These changes are modeled after user_update_7010().
887
  db_change_field('webform', 'confirmation_format', 'confirmation_format', array(
888
    'description' => 'The {filter_format}.format of the confirmation message.',
889
    'type' => 'int',
890
    'unsigned' => TRUE,
891
    'not null' => FALSE,
892
  ));
893
  db_update('webform')
894
    ->fields(array('confirmation_format' => NULL))
895
    ->condition('confirmation', '')
896
    ->condition('confirmation_format', 0)
897
    ->execute();
898
  $existing_formats = db_query("SELECT format FROM {filter_format}")->fetchCol();
899
  $default_format = variable_get('filter_default_format', 1);
900
901
  // Since Webform may be updated separately from Drupal core, not all format
902
  // names may be numbers when running this update.
903
  $numeric_formats = array();
904
  foreach ($existing_formats as $format_name) {
905
    if (is_numeric($format_name)) {
906
      $numeric_formats[] = (int) $format_name;
907
    }
908
  }
909
910
  $query = db_update('webform')
911
    ->fields(array('confirmation_format' => $default_format))
912
    ->isNotNull('confirmation_format');
913
914
  if (!empty($numeric_formats)) {
915
    $query->condition('confirmation_format', $numeric_formats, 'NOT IN');
916
  }
917
918
  $query->execute();
919
}
920
921
/**
922
 * Add columns for e-mail HTML and attachment settings.
923
 */
924
function webform_update_7302() {
925
  if (!db_field_exists('webform_emails', 'html')) {
926
    db_add_field('webform_emails', 'html', array('type' => 'int', 'size' => 'tiny', 'unsigned' => TRUE, 'default' => 0, 'not null' => TRUE));
927
    db_add_field('webform_emails', 'attachments', array('type' => 'int', 'size' => 'tiny', 'unsigned' => TRUE, 'default' => 0, 'not null' => TRUE));
928
  }
929
}
930
931
/**
932
 * Set the default for the "submit_notice" column to 1.
933
 */
934
function webform_update_7303() {
935
  db_change_field('webform', 'submit_notice', 'submit_notice', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 1));
936
}
937
938
/**
939
 * Add field for block feature and redirection setting.
940
 */
941
function webform_update_7304() {
942
  if (!db_field_exists('webform', 'block')) {
943
    db_add_field('webform', 'block', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
944
    db_change_field('webform', 'redirect_url', 'redirect_url', array('type' => 'varchar', 'length' => 255, 'default' => '<confirmation>'));
945
    db_update('webform')
946
      ->fields(array('redirect_url' => 'confirmation'))
947
      ->condition('redirect_url', '')
948
      ->execute();
949
  }
950
}
951
952
/**
953
 * Set additional_validate and additional_submit columns to allow NULL.
954
 */
955
function webform_update_7305() {
956
  if (db_field_exists('webform', 'additional_validate')) {
957
    db_change_field('webform', 'additional_validate', 'additional_validate', array('type' => 'text', 'not null' => FALSE));
958
    db_change_field('webform', 'additional_submit', 'additional_submit', array('type' => 'text', 'not null' => FALSE));
959
  }
960
}
961
962
/**
963
 * Add column for webform status (open or closed).
964
 */
965
function webform_update_7306() {
966
  if (!db_field_exists('webform', 'status')) {
967
    db_add_field('webform', 'status', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 1));
968
  }
969
}
970
971
/**
972
 * Update the confirmation_format column for default text format changes.
973
 */
974
function webform_update_7307() {
975
  // Update removed and moved to webform_update_7301().
976
  // See http://drupal.org/node/976102.
977
}
978
979
/**
980
 * Update the confirmation_format column to allow it to store strings.
981
 */
982
function webform_update_7308() {
983
  db_change_field('webform', 'confirmation_format', 'confirmation_format', array(
984
    'description' => 'The {filter_format}.format of the confirmation message.',
985
    'type' => 'varchar',
986
    'length' => 255,
987
    'not null' => FALSE,
988
  ));
989
}
990
991
/**
992
 * Add the ability to auto-save as draft between pages.
993
 */
994
function webform_update_7309() {
995
  if (!db_field_exists('webform', 'auto_save')) {
996
    db_add_field('webform', 'auto_save', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
997
  }
998
}
999
1000
/**
1001
 * Remove orphaned and unnecessary rows in the webform table.
1002
 */
1003
function webform_update_7310() {
1004
  $result = db_query("SELECT nid FROM {webform} WHERE
1005
    nid NOT IN
1006
    (SELECT DISTINCT(w1.nid) FROM {webform} w1 INNER JOIN {webform_component} wc ON w1.nid = wc.nid)
1007
    AND nid NOT IN
1008
    (SELECT w2.nid FROM {webform} w2 INNER JOIN {node} n ON w2.nid = n.nid WHERE n.type = 'webform')"
1009
  );
1010
  $empty_nids = array();
1011
  foreach ($result as $row) {
1012
    $empty_nids[] = $row->nid;
1013
  }
1014
  if (!empty($empty_nids)) {
1015
    db_delete('webform')->condition('nid', $empty_nids, 'IN')->execute();
1016
  }
1017
}
1018
1019
/**
1020
 * Add an index for nid_uid_sid to webform_submissions.
1021
 */
1022
function webform_update_7311() {
1023
  if (!db_index_exists('webform_submissions', 'nid_uid_sid')) {
1024
    db_add_index('webform_submissions', 'nid_uid_sid', array('nid', 'uid', 'sid'));
1025
  }
1026
}
1027
1028
/**
1029
 * Remove unused Webform variables.
1030
 */
1031
function webform_update_7312() {
1032
  variable_del('node_types');
1033
  variable_del('components');
1034
}
1035
1036
/**
1037
 * Convert the Date component start and end year options to start and end date.
1038
 */
1039
function webform_update_7313() {
1040
  $result = db_select('webform_component', 'wc', array('fetch' => PDO::FETCH_ASSOC))
1041
    ->fields('wc')
1042
    ->condition('type', 'date')
1043
    ->execute();
1044
  foreach ($result as $component) {
1045
    $component['extra'] = unserialize($component['extra']);
1046
    if (!isset($component['extra']['start_date']) && !isset($component['end_date'])) {
1047
      foreach (array('year_start' => 'start_date', 'year_end' => 'end_date') as $key => $replacement) {
1048
        $value = isset($component['extra'][$key]) ? trim($component['extra'][$key]) : '';
1049
        // Relative years.
1050
        if (preg_match('/[-+][ ]*[0-9]+/', $value)) {
1051
          $component['extra'][$replacement] = ($value == 1) ? ($value . ' year') : ($value . ' years');
1052
        }
1053
        // Absolute years.
1054
        elseif (is_numeric($value)) {
1055
          $component['extra'][$replacement] = 'Dec 31 ' . $value;
1056
        }
1057
        unset($component['extra'][$key]);
1058
      }
1059
      $component['extra'] = serialize($component['extra']);
1060
      drupal_write_record('webform_component', $component, array('nid', 'cid'));
1061
    }
1062
  }
1063
}
1064
1065
/**
1066
 * Add webform_last_download table to store last downloaded sid per user.
1067
 */
1068
function webform_update_7314() {
1069
  // Safety check to prevent recreating the webform_last_download table.
1070
  if (db_table_exists('webform_last_download')) {
1071
    return;
1072
  }
1073
1074
  $schema['webform_last_download'] = array(
1075
    'description' => 'Stores last submission number per user download.',
1076
    'fields' => array(
1077
      'nid' => array(
1078
        'description' => 'The node identifier of a webform.',
1079
        'type' => 'int',
1080
        'unsigned' => TRUE,
1081
        'not null' => TRUE,
1082
        'default' => 0,
1083
      ),
1084
      'uid' => array(
1085
        'description' => 'The user identifier.',
1086
        'type' => 'int',
1087
        'unsigned' => TRUE,
1088
        'not null' => TRUE,
1089
        'default' => 0,
1090
      ),
1091
      'sid' => array(
1092
        'description' => 'The last downloaded submission number.',
1093
        'type' => 'int',
1094
        'unsigned' => TRUE,
1095
        'not null' => TRUE,
1096
        'default' => 0,
1097
      ),
1098
    ),
1099
    'primary key' => array('nid', 'uid'),
1100
  );
1101
  db_create_table('webform_last_download', $schema['webform_last_download']);
1102
}
1103
1104
/**
1105
 * Add column for timestamp of last requested CSV download.
1106
 */
1107
function webform_update_7315() {
1108
  if (!db_field_exists('webform_last_download', 'requested')) {
1109 a45e4bc1 Assos Assos
    db_add_field('webform_last_download', 'requested', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
1110 85ad3d82 Assos Assos
  }
1111
}
1112
1113
/**
1114
 * Add additional columns for total submission limit.
1115
 */
1116
function webform_update_7316() {
1117
  if (!db_field_exists('webform', 'total_submit_limit')) {
1118
    db_add_field('webform', 'total_submit_limit', array('type' => 'int', 'not null' => TRUE, 'default' => -1));
1119
  }
1120
1121
  if (!db_field_exists('webform', 'total_submit_interval')) {
1122
    db_add_field('webform', 'total_submit_interval', array('type' => 'int', 'not null' => TRUE, 'default' => -1));
1123
  }
1124
}
1125
1126
/**
1127
 * Add an index for 'nid_sid' to webform_submissions.
1128
 */
1129
function webform_update_7317() {
1130
  // Even though we already have an index 'nid_uid_sid', adding the index for
1131
  // 'nid_sid' saves us a tablesort on the node/x/webform-results page.
1132
  if (!db_index_exists('webform_submissions', 'nid_sid')) {
1133
    db_add_index('webform_submissions', 'nid_sid', array('nid', 'sid'));
1134
  }
1135
}
1136
1137
/**
1138
 * Upgrade file components to support the new AJAX-upload element.
1139
 */
1140
function webform_update_7318() {
1141
  $result = db_select('webform_component', 'wc', array('fetch' => PDO::FETCH_ASSOC))
1142
    ->fields('wc')
1143
    ->condition('type', 'file')
1144
    ->execute();
1145
  foreach ($result as $component) {
1146
    $component['extra'] = unserialize($component['extra']);
1147
    if (!isset($component['extra']['directory'])) {
1148
      $component['extra']['directory'] = $component['extra']['savelocation'];
1149
      $component['extra']['scheme'] = file_default_scheme();
1150
      $component['extra']['filtering']['size'] = $component['extra']['filtering']['size'] . ' KB';
1151
      unset($component['extra']['savelocation']);
1152
      $component['extra'] = serialize($component['extra']);
1153
      drupal_write_record('webform_component', $component, array('nid', 'cid'));
1154
    }
1155
  }
1156
1157
  return t('File components updated to support AJAX uploading.');
1158
}
1159
1160
/**
1161
 * Add file usage entries for all files uploaded through Webform.
1162
 */
1163
function webform_update_7319(&$sandbox) {
1164
  if (!isset($sandbox['progress'])) {
1165
    // Initialize batch update information.
1166
    $sandbox['progress'] = 0;
1167
    $sandbox['last_fid_processed'] = -1;
1168
    $sandbox['max'] = db_select('file_managed')
1169
      ->condition('uri', '%' . db_like('://webform/') . '%', 'LIKE')
1170
      ->countQuery()
1171
      ->execute()
1172
      ->fetchField();
1173
  }
1174
1175
  // Process all files attached to a given revision during the same batch.
1176 a45e4bc1 Assos Assos
  $limit = webform_variable_get('webform_update_batch_size');
1177 85ad3d82 Assos Assos
  $files = db_select('file_managed', 'f')
1178
    ->fields('f')
1179
    ->condition('uri', '%' . db_like('://webform/') . '%', 'LIKE')
1180
    ->condition('fid', $sandbox['last_fid_processed'], '>')
1181
    ->orderBy('fid', 'ASC')
1182
    ->range(0, $limit)
1183
    ->execute()
1184
    ->fetchAllAssoc('fid', PDO::FETCH_ASSOC);
1185
1186
  // Determine each submission with which a file is associated.
1187
  if (!empty($files)) {
1188
    foreach ($files as $fid => $file) {
1189
      $file = (object) $file;
1190
      $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);
1191
      foreach ($sids as $sid => $row) {
1192
        // We use a db_merge() instead of file_usage_add() to prevent problems
1193
        // in the event this update was run twice. No file provided by Webform
1194
        // should ever be in use more than once at this point.
1195
        db_merge('file_usage')
1196
          ->key(array(
1197
            'fid' => $file->fid,
1198
            'type' => 'submission',
1199
            'module' => 'webform',
1200
            'id' => $sid,
1201
          ))
1202
          ->fields(array(
1203
            'count' => 1,
1204
          ))
1205
          ->execute();
1206
      }
1207
1208
      // Update our progress information for the batch update.
1209
      $sandbox['progress']++;
1210
      $sandbox['last_fid_processed'] = $file->fid;
1211
    }
1212
  }
1213
1214
  // If less than limit was processed, the update process is finished.
1215
  if (count($files) < $limit || $sandbox['progress'] == $sandbox['max']) {
1216
    $finished = TRUE;
1217
  }
1218
1219
  // If there's no max value then there's nothing to update and we're finished.
1220
  if (empty($sandbox['max']) || isset($finished)) {
1221
    return t('Webform file entries created in the file_usage table.');
1222
  }
1223
  else {
1224
    // Indicate our current progress to the batch update system.
1225
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
1226
  }
1227
}
1228
1229
/**
1230
 * Mark files uploaded through Webform that report active usage permanent.
1231
 */
1232
function webform_update_7320() {
1233
  db_query("UPDATE {file_managed} SET status = 1 WHERE fid IN (SELECT fid FROM {file_usage} WHERE module = :module_name)", array(':module_name' => 'webform'));
1234
}
1235
1236
/**
1237 a45e4bc1 Assos Assos
 * Rewrite token replacement system to use D7 tokens.
1238
 *
1239
 * If needed, please download and install the Token module from drupal.org.
1240
 * Otherwise some tokens will not be rendered.
1241
 */
1242
function webform_update_7401(&$sandbox) {
1243
  // Define replacements.
1244
  $patterns = array(
1245
    '%username',
1246
    '%useremail',
1247
    '%uid',
1248
    '%date',
1249
    '%ip_address',
1250
    '%site',
1251
    '%nid',
1252
    '%title',
1253
    '%email_values',
1254
    '%submission_url',
1255
    '%sid',
1256
    '%server[REQUEST_URI]',
1257 feca1e4a Assos Assos
    // Used to convert nested arrays of %value and %email.
1258
    '][',
1259 a45e4bc1 Assos Assos
  );
1260
  $replacements = array(
1261
    '[current-user:name]',
1262
    '[current-user:mail]',
1263
    '[current-user:uid]',
1264
    '[submission:date:long]',
1265
    '[current-user:ip-address]',
1266
    '[site:name]',
1267
    '[node:nid]',
1268
    '[node:title]',
1269
    '[submission:values]',
1270
    '[submission:url]',
1271
    '[submission:sid]',
1272
    '[current-page:url]',
1273 feca1e4a Assos Assos
    // Replace "][" with ":" for %value and %email.
1274
    ':',
1275 a45e4bc1 Assos Assos
  );
1276
  $dpatterns = array(
1277
    '/%get\[([^\]]+)\]/m',
1278
    '/%email\[([^% \n\r\t]+)?\]/m',
1279
    '/%value\[([^% \n\r\t]+)?\]/m',
1280
    '/%profile\[([^\]]+)\]/m',
1281
  );
1282
  $dreplacements = array(
1283
    '[current-page:query:$1]',
1284
    '[submission:values:$1]',
1285
    '[submission:values:$1:nolabel]',
1286
    '[current-user:$1]',
1287
  );
1288
1289
  $limit = webform_variable_get('webform_update_batch_size');
1290
  $processed_count = _webform_update_7401_batch($sandbox, $patterns, $replacements, $dpatterns, $dreplacements, $limit);
1291
1292
  // If less than limit was processed, the update process is finished.
1293
  if ($processed_count < $limit || $sandbox['progress'] == $sandbox['max']) {
1294
    $finished = TRUE;
1295
  }
1296
1297
  // If there's no max value then there's nothing to update and we're finished.
1298
  if (empty($sandbox['max']) || isset($finished)) {
1299
    $message = t('Your existing webforms have been upgraded to use the global Drupal 7 token system.');
1300
    if (!module_exists('token')) {
1301
      $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>';
1302
    }
1303
    return $message;
1304
  }
1305
  else {
1306
    // Indicate our current progress to the batch update system.
1307
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
1308
  }
1309
}
1310
1311
/**
1312
 * Utility function to update all the locations that use tokens.
1313
 */
1314
function _webform_update_7401_batch(&$sandbox, $patterns, $replacements, $dpatterns, $dreplacements, $limit) {
1315
  // Set up the initial batch process.
1316
  if (!isset($sandbox['progress'])) {
1317
    $sandbox['progress'] = 0;
1318
    $sandbox['last_nid_processed'] = -1;
1319
    $sandbox['max'] = db_select('webform')
1320
      ->countQuery()
1321
      ->execute()
1322
      ->fetchField();
1323
1324
    // Update tokens in variables.
1325
    $variables = array(
1326
      'webform_default_subject',
1327
      'webform_default_from_name',
1328
      'webform_default_from_address',
1329
    );
1330
    foreach ($variables as $variable) {
1331
      $value = variable_get($variable, NULL);
1332
      if ($value !== NULL) {
1333
        $value = str_replace($patterns, $replacements, $value);
1334
        $value = preg_replace($dpatterns, $dreplacements, $value);
1335
        variable_set($variable, $value);
1336
      }
1337
    }
1338
  }
1339
1340
  $webforms = db_select('webform', 'w')
1341
    ->fields('w')
1342
    ->condition('nid', $sandbox['last_nid_processed'], '>')
1343
    ->orderBy('nid', 'ASC')
1344
    ->range(0, $limit)
1345
    ->execute()
1346
    ->fetchAllAssoc('nid', PDO::FETCH_ASSOC);
1347
1348
  foreach ($webforms as $nid => $webform) {
1349
    // Update the webform record itself.
1350
    $original = $webform;
1351
    $parts = array(
1352
      'confirmation',
1353
      'redirect_url',
1354
    );
1355
    foreach ($parts as $part) {
1356
      $webform[$part] = str_replace($patterns, $replacements, $webform[$part]);
1357
      $webform[$part] = preg_replace($dpatterns, $dreplacements, $webform[$part]);
1358
    }
1359
    if ($webform != $original) {
1360
      drupal_write_record('webform', $webform, array('nid'));
1361
    }
1362
1363
    // Update tokens in component configurations.
1364
    $result = db_select('webform_component', 'wc', array('fetch' => PDO::FETCH_ASSOC))
1365
      ->fields('wc')
1366
      ->condition('wc.nid', $nid)
1367
      ->execute();
1368
    foreach ($result as $component) {
1369
      $original_extra = $component['extra'];
1370
      $original_value = $component['value'];
1371
      $component['extra'] = unserialize($component['extra']);
1372
      if (isset($component['extra']['description'])) {
1373
        $description = str_replace($patterns, $replacements, $component['extra']['description']);
1374
        $description = preg_replace($dpatterns, $dreplacements, $description);
1375
        $component['extra']['description'] = $description;
1376
      }
1377
      $component['extra'] = serialize($component['extra']);
1378
      $value = str_replace($patterns, $replacements, $component['value']);
1379
      $value = preg_replace($dpatterns, $dreplacements, $value);
1380
      $component['value'] = $value;
1381
      if ($component['extra'] != $original_extra || $component['value'] != $original_value) {
1382
        drupal_write_record('webform_component', $component, array('nid', 'cid'));
1383
      }
1384
    }
1385
1386
    // Update tokens in e-mail configurations.
1387
    $result = db_select('webform_emails', 'we', array('fetch' => PDO::FETCH_ASSOC))
1388
      ->fields('we')
1389
      ->condition('we.nid', $nid)
1390
      ->execute();
1391
    foreach ($result as $email) {
1392
      $parts = array(
1393
        'template',
1394
        'subject',
1395
        'from_name',
1396
      );
1397
      $original = $email;
1398
      foreach ($parts as $part) {
1399
        $email[$part] = str_replace($patterns, $replacements, $email[$part]);
1400
        $email[$part] = preg_replace($dpatterns, $dreplacements, $email[$part]);
1401
      }
1402
      if ($email != $original) {
1403
        drupal_write_record('webform_emails', $email, array('nid', 'eid'));
1404
      }
1405
    }
1406
1407
    // Update the last processed NID.
1408
    $sandbox['last_nid_processed'] = $nid;
1409
    $sandbox['progress']++;
1410
  }
1411
  return count($webforms);
1412
}
1413
1414
/**
1415
 * Add the webform_conditional database table.
1416
 */
1417
function webform_update_7402() {
1418
  // Sanity checks.
1419
  if (db_table_exists('webform_conditional')) {
1420
    // Both tables exist, so these are Webform-core provided tables.
1421
    if (db_table_exists('webform_conditional_rules')) {
1422
      return;
1423
    }
1424
    // Webform Conditional module was installed previously but not uninstalled.
1425
    else {
1426
      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".'));
1427
    }
1428
  }
1429
1430
  $schema['webform_conditional'] = array(
1431
    'description' => 'Holds information about conditional logic.',
1432
    'fields' => array(
1433
      'nid' => array(
1434
        'description' => 'The node identifier of a webform.',
1435
        'type' => 'int',
1436
        'unsigned' => TRUE,
1437
        'not null' => TRUE,
1438
        'default' => 0,
1439
      ),
1440
      'rgid' => array(
1441
        'description' => 'The rule group identifier for this group of rules.',
1442
        'type' => 'int',
1443
        'size' => 'small',
1444
        'unsigned' => TRUE,
1445
        'not null' => TRUE,
1446
        'default' => 0,
1447
      ),
1448
      'andor' => array(
1449
        'description' => 'Whether to AND or OR the actions in this group. All actions within the same crid should have the same andor value.',
1450
        'type' => 'varchar',
1451
        'length' => 128,
1452
      ),
1453
      'action' => array(
1454
        '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".',
1455
        'type' => 'varchar',
1456
        'length' => 128,
1457
      ),
1458
      'target_type' => array(
1459
        'description' => 'The type of target to be affected. Either "component" or "email". Indicates what type of ID the "target" column contains.',
1460
        'type' => 'varchar',
1461
        'length' => 128,
1462
      ),
1463
      'target' => array(
1464
        'description' => 'The ID of the target to be affected. Typically a component ID.',
1465
        'type' => 'varchar',
1466
        'length' => 128,
1467
      ),
1468
      'weight' => array(
1469
        'description' => 'Determines the position of this conditional compared to others.',
1470
        'type' => 'int',
1471
        'size' => 'small',
1472
        'not null' => TRUE,
1473
        'default' => 0,
1474
      ),
1475
    ),
1476
    'primary key' => array('nid', 'rgid'),
1477
  );
1478
1479
  $schema['webform_conditional_rules'] = array(
1480
    'description' => 'Holds information about conditional logic.',
1481
    'fields' => array(
1482
      'nid' => array(
1483
        'description' => 'The node identifier of a webform.',
1484
        'type' => 'int',
1485
        'unsigned' => TRUE,
1486
        'not null' => TRUE,
1487
        'default' => 0,
1488
      ),
1489
      'rgid' => array(
1490
        'description' => 'The rule group identifier for this group of rules.',
1491
        'type' => 'int',
1492
        'size' => 'small',
1493
        'unsigned' => TRUE,
1494
        'not null' => TRUE,
1495
        'default' => 0,
1496
      ),
1497
      'rid' => array(
1498
        'description' => 'The rule identifier for this conditional rule.',
1499
        'type' => 'int',
1500
        'size' => 'small',
1501
        'unsigned' => TRUE,
1502
        'not null' => TRUE,
1503
        'default' => 0,
1504
      ),
1505
      'source_type' => array(
1506
        'description' => 'The type of source on which the conditional is based. Currently always "component". Indicates what type of ID the "source" column contains.',
1507
        'type' => 'varchar',
1508
        'length' => 128,
1509
      ),
1510
      'source' => array(
1511
        'description' => 'The component ID being used in this condition.',
1512
        'type' => 'int',
1513
        'size' => 'small',
1514
        'unsigned' => TRUE,
1515
        'not null' => TRUE,
1516
        'default' => 0,
1517
      ),
1518
      'operator' => array(
1519
        'description' => 'Which operator (equal, contains, starts with, etc.) should be used for this comparison between the source and value?',
1520
        'type' => 'varchar',
1521
        'length' => 128,
1522
      ),
1523
      'value' => array(
1524
        'description' => 'The value to be compared with source.',
1525
        'type' => 'text',
1526
      ),
1527
    ),
1528
    'primary key' => array('nid', 'rgid', 'rid'),
1529
  );
1530
1531
  db_create_table('webform_conditional', $schema['webform_conditional']);
1532
  db_create_table('webform_conditional_rules', $schema['webform_conditional_rules']);
1533
  // Rebuild schema so that webform_update_7403() can use drupal_write_record().
1534
  if (db_table_exists('system') && db_field_exists('system', 'status')) {
1535
    drupal_get_schema(NULL, TRUE);
1536
  }
1537
}
1538
1539
/**
1540
 * Convert per-component conditionals to new more flexible conditional system.
1541
 */
1542
function webform_update_7403(&$sandbox) {
1543
  // Set up the initial batch process.
1544
  if (!isset($sandbox['progress'])) {
1545
    $sandbox['progress'] = 0;
1546
    $sandbox['last_nid_processed'] = -1;
1547
    $sandbox['converted_count'] = 0;
1548
    $sandbox['max'] = db_select('webform')
1549
      ->countQuery()
1550
      ->execute()
1551
      ->fetchField();
1552
  }
1553
1554
  $limit = webform_variable_get('webform_update_batch_size');
1555
  $webforms = db_select('webform', 'w')
1556
    ->fields('w')
1557
    ->condition('nid', $sandbox['last_nid_processed'], '>')
1558
    ->orderBy('nid', 'ASC')
1559
    ->range(0, $limit)
1560
    ->execute()
1561
    ->fetchAllAssoc('nid', PDO::FETCH_ASSOC);
1562
1563
  foreach ($webforms as $nid => $webform) {
1564
    // Update tokens in component configurations.
1565
    $result = db_select('webform_component', 'wc', array('fetch' => PDO::FETCH_ASSOC))
1566
      ->fields('wc')
1567
      ->condition('wc.nid', $nid)
1568
      ->execute();
1569
    $rgid = 0;
1570
    foreach ($result as $component) {
1571
      // For each component, check if it has conditional properties that need
1572
      // to be removed and/or migrated. Because these properties may be in any
1573
      // order, copy the original extra array for comparison.
1574
      $component['extra'] = unserialize($component['extra']);
1575
      $original_extra = $component['extra'];
1576
1577
      // Remove conditional properties if present.
1578
      if (isset($component['extra']['conditional_component'])) {
1579
        unset($component['extra']['conditional_component']);
1580
      }
1581
      if (isset($component['extra']['conditional_operator'])) {
1582
        unset($component['extra']['conditional_operator']);
1583
      }
1584
      if (isset($component['extra']['conditional_values'])) {
1585
        unset($component['extra']['conditional_values']);
1586
1587
        // If the component has conditional values specified, that indicates
1588
        // that this component was conditionally shown. Convert it to a new
1589
        // conditional with multiple rules if needed.
1590
        if (strlen(trim($original_extra['conditional_values'])) && !empty($original_extra['conditional_operator']) && !empty($original_extra['conditional_component'])) {
1591
          $conditional_values = explode("\n", $original_extra['conditional_values']);
1592
          $rules = array();
1593
          $rule = array(
1594
            'nid' => $nid,
1595
            'rgid' => $rgid,
1596
            'rid' => NULL,
1597
            'source_type' => 'component',
1598
            'source' => $original_extra['conditional_component'],
1599
            'operator' => 'equal',
1600
            'value' => NULL,
1601
          );
1602
          foreach ($conditional_values as $value) {
1603
            $value = trim($value);
1604
            if ($value) {
1605
              $new_rule = $rule;
1606
              $new_rule['rid'] = count($rules);
1607
              $new_rule['value'] = $value;
1608
              $rules[] = $new_rule;
1609
            }
1610
          }
1611
          if (count($rules)) {
1612
            $conditional = array(
1613
              'nid' => $nid,
1614
              'rgid' => $rgid,
1615
              'andor' => 'or',
1616
              'action' => ($original_extra['conditional_operator'] === '=') ? 'show' : 'hide',
1617
              'target_type' => 'component',
1618
              'target' => $component['cid'],
1619
              'weight' => 0,
1620
            );
1621 6a93dd76 Assos Assos
1622
            // Cannot use drupal_write_record for webform_conditional because
1623
            // the current schema has fewer fields than the schema in use during
1624
            // this hook_update_N function.
1625
            db_insert('webform_conditional')
1626
              ->fields($conditional)
1627
              ->execute();
1628 a45e4bc1 Assos Assos
            foreach ($rules as $rule) {
1629
              drupal_write_record('webform_conditional_rules', $rule);
1630
            }
1631
            $sandbox['converted_count']++;
1632
            $rgid++;
1633
          }
1634
        }
1635
      }
1636
1637
      // Update the component with the conditional properties removed.
1638
      if ($component['extra'] != $original_extra) {
1639
        $component['extra'] = serialize($component['extra']);
1640
        drupal_write_record('webform_component', $component, array('nid', 'cid'));
1641
      }
1642
    }
1643
1644
    // Update the last processed NID.
1645
    $sandbox['last_nid_processed'] = $nid;
1646
    $sandbox['progress']++;
1647
  }
1648
1649
  // If less than limit was processed, the update process is finished.
1650
  if (count($webforms) < $limit || $sandbox['progress'] == $sandbox['max']) {
1651
    $finished = TRUE;
1652
  }
1653
1654
  // If there's no max value then there's nothing to update and we're finished.
1655
  if (empty($sandbox['max']) || isset($finished)) {
1656
    return t('@count webforms using conditionals updated to the new conditional system.', array('@count' => $sandbox['converted_count']));
1657
  }
1658
  else {
1659
    // Indicate our current progress to the batch update system.
1660
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
1661
  }
1662
}
1663
1664
/**
1665 01f36513 Assos Assos
 * Remove files left over from deleted submissions.
1666
 *
1667
 * Such files are now deleted automatically.
1668 85ad3d82 Assos Assos
 */
1669 a45e4bc1 Assos Assos
function webform_update_7404() {
1670 85ad3d82 Assos Assos
  module_load_include('inc', 'webform', 'components/file');
1671 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();
1672 85ad3d82 Assos Assos
  foreach ($fids as $fid) {
1673
    _webform_delete_file(NULL, array($fid));
1674
  }
1675
}
1676 c22e192e Assos Assos
1677
/**
1678 a45e4bc1 Assos Assos
 * Add an "extra" column to the e-mail table for for non-queryable options.
1679 c22e192e Assos Assos
 */
1680 a45e4bc1 Assos Assos
function webform_update_7405() {
1681
  $schema = array(
1682
    '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.',
1683
    'type' => 'text',
1684
    'not null' => TRUE,
1685
    'initial' => '',
1686
  );
1687
  if (!db_field_exists('webform_emails', 'extra')) {
1688
    db_add_field('webform_emails', 'extra', $schema);
1689
  }
1690
}
1691
1692
/**
1693
 * Convert the "webform_use_cookies" setting to "webform_tracking_mode".
1694
 */
1695
function webform_update_7406() {
1696
  // Previously, we only had "strict" and "ip_address" checking. Using cookies
1697
  // meant cookies in addition to IP address.
1698
  $use_cookies = variable_get('webform_use_cookies');
1699
  if (isset($use_cookies)) {
1700
    variable_set('webform_tracking_mode', $use_cookies ? 'strict' : 'ip_address');
1701
    variable_del('webform_use_cookies');
1702
  }
1703
}
1704
1705
/**
1706
 * Remove orphaned conditional rules.
1707
 */
1708
function webform_update_7407() {
1709
  // Delete entire conditions for deleted components that were the target.
1710
  // This query is complicated by database compatibility since we're joining two
1711
  // non-matching columns. See http://drupal.org/node/2026891.
1712
  $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");
1713
  foreach ($result as $row) {
1714
    db_delete('webform_conditional')
1715
      ->condition('nid', $row->nid)
1716
      ->condition('rgid', $row->rgid)
1717
      ->execute();
1718
    db_delete('webform_conditional_rules')
1719
      ->condition('nid', $row->nid)
1720
      ->condition('rgid', $row->rgid)
1721
      ->execute();
1722
  }
1723
  // Delete conditional rules for deleted components that were the source.
1724
  $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");
1725
  foreach ($result as $row) {
1726
    db_delete('webform_conditional_rules')
1727
      ->condition('nid', $row->nid)
1728
      ->condition('rgid', $row->rgid)
1729
      ->condition('rid', $row->rid)
1730
      ->execute();
1731
  }
1732
  // Delete any conditions that no longer have any rules left in them.
1733
  $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");
1734
  foreach ($result as $row) {
1735
    db_delete('webform_conditional')
1736
      ->condition('nid', $row->nid)
1737
      ->condition('rgid', $row->rgid)
1738
      ->execute();
1739
  }
1740
}
1741
1742
/**
1743
 * Rename the "mandatory" column to "required".
1744
 */
1745
function webform_update_7408() {
1746
  $spec = array(
1747
    'description' => 'Boolean flag for if this component is required.',
1748
    'type' => 'int',
1749
    'size' => 'tiny',
1750
    'not null' => TRUE,
1751
    'default' => 0,
1752
  );
1753
  if (!db_field_exists('webform_component', 'required')) {
1754
    db_change_field('webform_component', 'mandatory', 'required', $spec);
1755
  }
1756
}
1757
1758
/**
1759
 * Add progress bar columns to the webform table.
1760
 */
1761
function webform_update_7409() {
1762
  if (!db_field_exists('webform', 'progressbar_bar')) {
1763
    $int_schema = array(
1764
      'type' => 'int',
1765
      'size' => 'tiny',
1766
      'not null' => TRUE,
1767
      'default' => 0,
1768
    );
1769
    $varchar_schema = array(
1770
      'type' => 'varchar',
1771
      'length' => 255,
1772
    );
1773
1774
    $int_schema['description'] = 'Boolean value indicating if the bar should be shown as part of the progress bar.';
1775
    db_add_field('webform', 'progressbar_bar', $int_schema);
1776
1777
    $int_schema['description'] = 'Boolean value indicating if the page number should be shown as part of the progress bar.';
1778
    db_add_field('webform', 'progressbar_page_number', $int_schema);
1779
1780
    $int_schema['description'] = 'Boolean value indicating if the percentage complete should be shown as part of the progress bar.';
1781
    db_add_field('webform', 'progressbar_percent', $int_schema);
1782
1783
    $int_schema['description'] = 'Boolean value indicating if the pagebreak labels should be included as part of the progress bar.';
1784
    db_add_field('webform', 'progressbar_pagebreak_labels', $int_schema);
1785
1786
    $int_schema['description'] = 'Boolean value indicating if the confirmation page should count as a page in the progress bar.';
1787
    db_add_field('webform', 'progressbar_include_confirmation', $int_schema);
1788
1789
    $varchar_schema['description'] = 'Label for the first page of the progress bar.';
1790
    db_add_field('webform', 'progressbar_label_first', $varchar_schema);
1791
1792
    $varchar_schema['description'] = 'Label for the last page of the progress bar.';
1793
    db_add_field('webform', 'progressbar_label_confirmation', $varchar_schema);
1794
1795
    return t('New webform columns added.');
1796
  }
1797
}
1798
1799
/**
1800
 * Remove the "teaser" column from the "webform" table.
1801
 */
1802
function webform_update_7410() {
1803
  if (db_field_exists('webform', 'teaser')) {
1804
    db_drop_field('webform', 'teaser');
1805
    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.');
1806
  }
1807
}
1808
1809
/**
1810
 * Remove [submission:values:x] token use of :nolabel and add :withlabel.
1811
 */
1812
function webform_update_7411(&$sandbox) {
1813
  // Define replacements.
1814
  $patterns = array();
1815
  $replacements = array();
1816
  $dpatterns = array(
1817
    '/\[submission:values(:(?!nolabel)[a-z_]+)+\]/m',
1818
    '/\[submission:values(:([a-z_:]+))?:nolabel\]/m',
1819
  );
1820
  $dreplacements = array(
1821
    '[submission:values$1:withlabel]',
1822
    '[submission:values$1]',
1823
  );
1824
1825
  $limit = webform_variable_get('webform_update_batch_size');
1826
  $processed_count = _webform_update_7401_batch($sandbox, $patterns, $replacements, $dpatterns, $dreplacements, $limit);
1827
1828
  // If less than limit was processed, the update process is finished.
1829
  if ($processed_count < $limit || $sandbox['progress'] == $sandbox['max']) {
1830
    $finished = TRUE;
1831
  }
1832
1833
  // If there's no max value then there's nothing to update and we're finished.
1834
  if (empty($sandbox['max']) || isset($finished)) {
1835
    return t('Replaced tokens using [submission:values:x] with [submission:values:x:withlabel].');
1836
  }
1837
  else {
1838
    // Indicate our current progress to the batch update system.
1839
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
1840
  }
1841
}
1842
1843
/**
1844
 * Split webform_node_types as content type specific.
1845
 */
1846
function webform_update_7412() {
1847
  $types = variable_get('webform_node_types', array('webform'));
1848
  foreach ($types as $type) {
1849
    variable_set('webform_node_' . $type, TRUE);
1850
  }
1851
  variable_del('webform_node_types');
1852
}
1853
1854
/**
1855
 * Add preview page columns to the webform table.
1856
 */
1857
function webform_update_7413() {
1858
  if (!db_field_exists('webform', 'preview')) {
1859
    $int_schema = array(
1860
      'type' => 'int',
1861
      'size' => 'tiny',
1862
      'not null' => TRUE,
1863
      'default' => 0,
1864
    );
1865
    $varchar_schema = array(
1866
      'type' => 'varchar',
1867
      'length' => 255,
1868
    );
1869
    $text_schema = array(
1870
      'type' => 'text',
1871
      'not null' => TRUE,
1872
      'initial' => '',
1873
    );
1874
1875
    $int_schema['description'] = 'Boolean value indicating if this form includes a page for previewing the submission.';
1876
    db_add_field('webform', 'preview', $int_schema);
1877
1878
    $varchar_schema['description'] = 'The text for the button that will proceed to the preview page.';
1879
    db_add_field('webform', 'preview_next_button_label', $varchar_schema);
1880
1881
    $varchar_schema['description'] = 'The text for the button to go backwards from the preview page.';
1882
    db_add_field('webform', 'preview_prev_button_label', $varchar_schema);
1883
1884
    $varchar_schema['description'] = 'The title of the preview page, as used by the progress bar.';
1885
    db_add_field('webform', 'preview_title', $varchar_schema);
1886
1887
    $text_schema['description'] = 'Text shown on the preview page of the form.';
1888
    db_add_field('webform', 'preview_message', $text_schema);
1889
1890
    $varchar_schema['description'] = 'The {filter_format}.format of the preview page message.';
1891
    db_add_field('webform', 'preview_message_format', $varchar_schema);
1892
1893
    $text_schema['description'] = 'Comma-separated list of component IDs that should not be included in this form\'s confirmation page.';
1894
    db_add_field('webform', 'preview_excluded_components', $text_schema);
1895
1896
    return t('New webform columns added.');
1897
  }
1898
}
1899
1900
/**
1901
 * Change email subject, from_name and from_address fields to type 'TEXT'.
1902
 */
1903
function webform_update_7414() {
1904
  $schema = array(
1905
    'subject' => array(
1906
      '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.',
1907
      'type' => 'text',
1908
      'not null' => FALSE,
1909
    ),
1910
    'from_name' => array(
1911
      '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.',
1912
      'type' => 'text',
1913
      'not null' => FALSE,
1914
    ),
1915
    'from_address' => array(
1916
      '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.',
1917
      'type' => 'text',
1918
      'not null' => FALSE,
1919
    ),
1920
  );
1921
1922
  db_change_field('webform_emails', 'subject', 'subject', $schema['subject']);
1923
  db_change_field('webform_emails', 'from_name', 'from_name', $schema['from_name']);
1924
  db_change_field('webform_emails', 'from_address', 'from_address', $schema['from_address']);
1925
1926
  return t('Custom email columns successfully changed.');
1927
}
1928
1929
/**
1930
 * Increase length of webform.redirect_url.
1931
 */
1932
function webform_update_7415() {
1933
  $spec = array(
1934
    'description' => 'The URL a user is redirected to after submitting a form.',
1935
    'type' => 'varchar',
1936
    'length' => 2048,
1937
    'default' => '<confirmation>',
1938
  );
1939
  db_change_field('webform', 'redirect_url', 'redirect_url', $spec);
1940
}
1941
1942
/**
1943
 * Add columns for serial numbered submissions. Add serial numbers to existing submissions.
1944
 */
1945
function webform_update_7416() {
1946
  // SQL database implementations vary in how DDL statements are handled within
1947
  // transactions. Since this update routine should be run in maintenance mode
1948
  // without concurrent transactions, no DDL statements are executed within a
1949
  // transaction.
1950
  // Add next_serial column to webform.
1951
  $spec = array(
1952
    'description' => 'The serial number to give to the next submission to this webform.',
1953
    'type' => 'int',
1954
    'unsigned' => TRUE,
1955
    'not null' => TRUE,
1956
    'default' => 1,
1957
  );
1958
  if (!db_field_exists('webform', 'next_serial')) {
1959
    db_add_field('webform', 'next_serial', $spec);
1960
  }
1961
1962
  // Add serial column to webform_submissions.
1963
  $spec = array(
1964
    'description' => 'The serial number of this submission.',
1965
    'type' => 'int',
1966
    'unsigned' => TRUE,
1967
  );
1968
  if (!db_field_exists('webform_submissions', 'serial')) {
1969
    db_add_field('webform_submissions', 'serial', $spec);
1970
  }
1971
1972
  // Begin a transaction for updating the serial numbers. The transaction will
1973
  // commit when $txn is unset or goesout-of-scope.
1974
  $txn = db_transaction();
1975
1976
  // Delete stray entries from the Webform tables before adding serial numbers.
1977
  db_query("DELETE FROM {webform_submissions} WHERE nid NOT IN (SELECT nid FROM {webform})");
1978
  db_query("DELETE FROM {webform_submitted_data} WHERE nid NOT IN (SELECT nid FROM {webform})");
1979
1980
  // Add serial numbers to all submissions.
1981
  // Repeat for every Webform.
1982
  $nids = db_select('webform', 'w')
1983
    ->fields('w', array('nid'))
1984
    ->execute();
1985
  while ($nid = $nids->fetchColumn()) {
1986
    $serial = 1;
1987
    // Repeat for every submission in this Webform.
1988
    $sids = db_select('webform_submissions', 'ws')
1989
      ->forUpdate()
1990
      ->fields('ws', array('sid'))
1991
      ->condition('nid', $nid)
1992
      ->orderBy('sid')
1993
      ->execute();
1994
    while ($sid = $sids->fetchColumn()) {
1995
      // Set the serial number.
1996
      db_update('webform_submissions')
1997
        ->fields(array('serial' => $serial))
1998
        ->condition('nid', $nid)
1999
        ->condition('sid', $sid)
2000
        ->execute();
2001
      $serial++;
2002
    }
2003
    // Set the next serial number.
2004
    db_update('webform')
2005
      ->fields(array('next_serial' => $serial))
2006
      ->condition('nid', $nid)
2007
      ->execute();
2008
  }
2009 feca1e4a Assos Assos
  // Commit the transaction.
2010 a45e4bc1 Assos Assos
  unset($txn);
2011
2012
  // Now that every submission has a serial number, make serial numbers required.
2013
  $spec['not null'] = TRUE;
2014
  $keys = array();
2015
  // Create a unique index if it does not already exist.
2016
  if (!db_index_exists('webform_submissions', 'nid_serial')) {
2017
    $keys = array(
2018
      'unique keys' => array(
2019
        'nid_serial' => array('nid', 'serial'),
2020
      ),
2021
    );
2022
  }
2023
  db_change_field('webform_submissions', 'serial', 'serial', $spec, $keys);
2024
2025
  return t('Columns for serial numbered submissions successfully added. Serial numbers added to existing submissions.');
2026
}
2027
2028
/**
2029
 * Change webform_component.name to text to allow for longer labels.
2030
 */
2031
function webform_update_7417() {
2032 ba09eb79 Assos Assos
  // This update function was introduced in 7.x-4.0rc1, which was the first
2033
  // release to require views. While the views requirement was added to the
2034
  // .info file, and while subsequently hook_requirements() added a check for
2035
  // views, it is possible to arrive at this update function via drush updatedb
2036
  // without views enabled.
2037
  $result = NULL;
2038
  if (!module_exists('views')) {
2039
    if (module_enable(array('views'))) {
2040
      $result = t('The Views module was automatically enabled.');
2041
    }
2042
    else {
2043
      throw new DrupalUpdateException(t('UPDATE ERROR: The Views module must be downloaded and enabled before Webform updates can proceed.'));
2044
    }
2045
  }
2046
2047 a45e4bc1 Assos Assos
  db_change_field('webform_component', 'name', 'name', array('type' => 'text', 'not null' => TRUE));
2048 ba09eb79 Assos Assos
  return $result;
2049 a45e4bc1 Assos Assos
}
2050
2051
/**
2052 01f36513 Assos Assos
 * Upgrade the "extra" column in the e-mail table.
2053
 *
2054
 * Make the column consistent with a new webform installation.
2055 a45e4bc1 Assos Assos
 *
2056
 * In version 7.x-4.0-rc6 and earlier, the extra field was added with 'not null'
2057
 * FALSE, cause the schema module to report in mismatch. While functionally this
2058
 * causes no problem, this update removes the schema module's warning.
2059
 */
2060
function webform_update_7418() {
2061
  // While there should never be any NULL values in the extra field, change them to '' to be safe.
2062
  db_update('webform_emails')
2063
    ->fields(array('extra' => ''))
2064
    ->isNull('extra')
2065
    ->execute();
2066
  // Pass a complete field specification to db_change_field for cross-database compatiblity.
2067
  $spec = array(
2068
    '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.',
2069
    'type' => 'text',
2070
    'not null' => TRUE,
2071
  );
2072
  db_change_field('webform_emails', 'extra', 'extra', $spec);
2073
}
2074
2075
/**
2076
 * Add an index on submitted data.
2077
 */
2078
function webform_update_7419() {
2079
  // Note: MS SQL Server does not support size-limited indexes and the column
2080
  // type (text) is too big to fit inside index size limits.
2081
  if (!db_index_exists('webform_submitted_data', 'data') && db_driver() != 'sqlsrv') {
2082
    db_add_index('webform_submitted_data', 'data', array(array('data', 64)));
2083
  }
2084
}
2085
2086
/**
2087
 * Extend access to the WEBFORM tab to anyone who can access the node's EDIT tab.
2088
 */
2089
function webform_update_7420() {
2090
  user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('edit webform components'));
2091
}
2092
2093
/**
2094
 * Set the administrator option for an HTML-capable mail system to the current automatically-detected option.
2095
 */
2096
function webform_update_7421() {
2097
  $capable = array_reduce(array('mandrill', 'mimemail', 'htmlmail'),
2098 feca1e4a Assos Assos
                          function ($carry, $module) {
2099
                            return $carry || module_exists($module);
2100
                          },
2101 a45e4bc1 Assos Assos
                          FALSE);
2102
  variable_set('webform_email_html_capable', $capable);
2103
  return $capable
2104
            ? t('An HTML-capable module is installed. The option to send HTML e-mail is enabled.')
2105
            : t('No commonly-known HTML capable module is installed. The option to send HTML e-mail is disabled.');
2106
}
2107
2108
/**
2109
 * Remove the administrator option "Include webform forms in search index" and rely on the Search Index view mode instead.
2110
 */
2111
function webform_update_7422() {
2112
  variable_del('webform_search_index');
2113
  return module_exists('search')
2114
          ? t('Webform forms will now be included in the search index only if the Webform "field" is displayed in the "Search index" view mode.')
2115
          : NULL;
2116
}
2117
2118
/**
2119
 * 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.
2120
 */
2121
function webform_update_7423() {
2122
  // Create webform_condtional_actions table.
2123 feca1e4a Assos Assos
  // The table might already exist if this update previously timed-out.
2124 a45e4bc1 Assos Assos
  if (!db_table_exists('webform_conditional_actions')) {
2125
    $schema['webform_conditional_actions'] = array(
2126
      'description' => 'Holds information about conditional actions.',
2127
      'fields' => array(
2128
        'nid' => array(
2129
          'description' => 'The node identifier of a webform.',
2130
          'type' => 'int',
2131
          'unsigned' => TRUE,
2132
          'not null' => TRUE,
2133
          'default' => 0,
2134
        ),
2135
        'rgid' => array(
2136
          'description' => 'The rule group identifier for this group of rules.',
2137
          'type' => 'int',
2138
          'size' => 'small',
2139
          'unsigned' => TRUE,
2140
          'not null' => TRUE,
2141
          'default' => 0,
2142
        ),
2143
        'aid' => array(
2144
          'description' => 'The rule identifier for this conditional action.',
2145
          'type' => 'int',
2146
          'size' => 'small',
2147
          'unsigned' => TRUE,
2148
          'not null' => TRUE,
2149
          'default' => 0,
2150
        ),
2151
        'target_type' => array(
2152
          'description' => 'The type of target to be affected. Currently always "component". Indicates what type of ID the "target" column contains.',
2153
          'type' => 'varchar',
2154
          'length' => 128,
2155
        ),
2156
        'target' => array(
2157
          'description' => 'The ID of the target to be affected. Typically a component ID.',
2158
          'type' => 'varchar',
2159
          'length' => 128,
2160
        ),
2161
        'invert' => array(
2162
          'description' => 'If inverted, execute when rule(s) are false.',
2163
          'type' => 'int',
2164
          'size' => 'small',
2165
          'unsigned' => TRUE,
2166
          'not null' => TRUE,
2167
          'default' => 0,
2168
        ),
2169
        'action' => array(
2170
          'description' => 'The action to be performed on the target.',
2171
          'type' => 'varchar',
2172
          'length' => 128,
2173
        ),
2174
        'argument' => array(
2175
          'description' => 'Optional argument for action.',
2176
          'type' => 'text',
2177
        ),
2178
      ),
2179
      'primary key' => array('nid', 'rgid', 'aid'),
2180
    );
2181
    db_create_table('webform_conditional_actions', $schema['webform_conditional_actions']);
2182
  }
2183
2184
  // In a site with many, many conditionals, the db_insert may timeout. Start a transaction to ensure atomic action.
2185
  $tx = db_transaction();
2186
  // Copy target information from existing webform_conditional table to new webfrom_condtional_actions table.
2187
  $select = db_select('webform_conditional', 'c')
2188
    ->fields('c', array('nid', 'rgid', 'action', 'target_type', 'target'))
2189
    ->orderBy('nid')->orderBy('rgid');
2190
  $select->addExpression("''", 'argument');
2191
  db_insert('webform_conditional_actions')
2192
    ->from($select)
2193
    ->execute();
2194
2195 feca1e4a Assos Assos
  // Commit the insert.
2196 a45e4bc1 Assos Assos
  unset($tx);
2197
2198
  // Remove unneeded columns from webform_conditional.
2199
  foreach (array('action', 'target_type', 'target') as $fieldname) {
2200
    if (db_field_exists('webform_conditional', $fieldname)) {
2201
      db_drop_field('webform_conditional', $fieldname);
2202
    }
2203
  }
2204
2205
  // Rebuild the registry because this point release contains a new class: WebformConditionals.
2206
  registry_rebuild();
2207
2208
  return t('Webform database tables were successfully adjusted to allow more than one action for each conditional.');
2209
}
2210
2211
/**
2212
 * Convert conditional actions of "hide" to "isn't shown".
2213
 */
2214
function webform_update_7424() {
2215
  $count = db_update('webform_conditional_actions')
2216
    ->fields(array('action' => 'show', 'invert' => 1))
2217
    ->condition('action', 'hide')
2218
    ->execute();
2219
  return format_plural($count,
2220
                       '1 "hide" conditional converted to "isn\'t" shown.',
2221
                       '@count conditionals converted to "isn\'t" shown.');
2222
}
2223
2224
/**
2225
 * Add "exclude empty" option to emails.
2226
 */
2227
function webform_update_7425() {
2228
  // Add next_serial column to webform.
2229
  $spec = array(
2230
    'description' => 'Determines if the e-mail will include component with an empty value.',
2231
    'type' => 'int',
2232
    'unsigned' => TRUE,
2233
    'size' => 'tiny',
2234
    'not null' => TRUE,
2235
    'default' => 0,
2236
  );
2237
  if (!db_field_exists('webform_emails', 'exclude_empty')) {
2238
    db_add_field('webform_emails', 'exclude_empty', $spec);
2239
  }
2240
2241
  // Clear the views cache since this release use the webform_analysis view.
2242
  cache_clear_all('*', 'cache_views', TRUE);
2243
2244
  return t('Webform e-mails were sucessfully updated to add the option to exclude empty components.');
2245
}
2246
2247
/**
2248
 * Add configuration to continue sending individual e-mails to multiple recipients.
2249
 */
2250
function webform_update_7426() {
2251
  variable_set('webform_email_address_individual', 1);
2252
}
2253
2254
/**
2255
 * Add database columns for submission completed and modified timestamps. Sites with many submissions may wish to use drush to execute this update.
2256
 */
2257
function webform_update_7427() {
2258
  // Create new timestamp columns.
2259
  $specs = array(
2260
    'completed' => array(
2261
      'description' => 'Timestamp when the form was submitted as complete (not draft).',
2262
      'type' => 'int',
2263
      'not null' => TRUE,
2264
      'default' => 0,
2265
    ),
2266
    'modified' => array(
2267
      'description' => 'Timestamp when the form was last saved (complete or draft).',
2268
      'type' => 'int',
2269
      'not null' => TRUE,
2270
      'default' => 0,
2271
    ),
2272
  );
2273
  foreach ($specs as $field_name => $spec) {
2274
    if (!db_field_exists('webform_submissions', $field_name)) {
2275
      db_add_field('webform_submissions', $field_name, $spec);
2276
    }
2277
  }
2278
2279
  // In a site with many submissions, the db_update may timeout. Start a transaction to ensure atomic action.
2280
  $tx = db_transaction();
2281
  // Copy submitted to completed for non-draft submissions.
2282
  db_update('webform_submissions')
2283
    ->expression('completed', 'submitted')
2284
    ->condition('is_draft', 0)
2285
    ->execute();
2286
  // Commit the update.
2287
  unset($tx);
2288
2289
  // Start another transaction.
2290
  $tx = db_transaction();
2291
  db_update('webform_submissions')
2292
    ->expression('modified', 'submitted')
2293
    ->execute();
2294
  // Commit the update.
2295
  unset($tx);
2296
2297
  // Clear the views cache since to see the completed and modified views fields.
2298
  cache_clear_all('*', 'cache_views', TRUE);
2299
2300
  return t('Webform submissions were updated with completed and modified timestamps.');
2301
}
2302
2303
/**
2304
 * Add a "confidential" option to webforms.
2305
 */
2306
function webform_update_7428() {
2307
  // Add confidential column to webform.
2308
  if (!db_field_exists('webform', 'confidential')) {
2309
    $spec = array(
2310
      'description' => 'Boolean value for whether to anonymize submissions.',
2311
      'type' => 'int',
2312
      'size' => 'tiny',
2313
      'not null' => TRUE,
2314
      'default' => 0,
2315
    );
2316
    db_add_field('webform', 'confidential', $spec);
2317
  }
2318
2319
  return t('Webforms may now be configured to anonymize confidential submissions.');
2320
}
2321
2322
/**
2323
 * 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'.
2324
 */
2325
function webform_update_7429() {
2326
  // Add highest_valid_page column to webform_submissions.
2327
  if (!db_field_exists('webform_submissions', 'highest_valid_page')) {
2328
    $spec = array(
2329
      'description' => 'For drafts, the highest validated page number.',
2330
      'type' => 'int',
2331
      'size' => 'small',
2332
      'not null' => TRUE,
2333
      'default' => 0,
2334
    );
2335
    db_add_field('webform_submissions', 'highest_valid_page', $spec);
2336
  }
2337
2338
  return t('Webforms will now resume draft submissions on the page where the submitter left off.');
2339
}
2340
2341
/**
2342
 * Add a column to the emails table to allow disabling.
2343
 */
2344
function webform_update_7430() {
2345
  // Add status column to webform_emails.
2346
  if (!db_field_exists('webform_emails', 'status')) {
2347
    $spec = array(
2348
      'description' => 'Whether this email is enabled.',
2349
      'type' => 'int',
2350
      'unsigned' => TRUE,
2351
      'size' => 'tiny',
2352
      'not null' => TRUE,
2353
      'default' => 1,
2354
    );
2355
    db_add_field('webform_emails', 'status', $spec);
2356
  }
2357
2358
  return t('Webform emails may now be disabled.');
2359 c22e192e Assos Assos
}