/[drupal]/contributions/modules/webform/webform.install
ViewVC logotype

Contents of /contributions/modules/webform/webform.install

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.27 - (show annotations) (download) (as text)
Fri Jun 19 19:16:24 2009 UTC (5 months, 1 week ago) by djalloway
Branch: MAIN
CVS Tags: HEAD
Changes since 1.26: +18 -1 lines
File MIME type: text/x-php
#470440: Allow previous-submission-notifications to be disabled per form.
1 <?php
2 // $Id: webform.install,v 1.26 2009/06/17 23:01:31 quicksketch Exp $
3
4 /**
5 * @file
6 * Webform module install/schema hooks.
7 */
8
9 /**
10 * Implementation of hook_schema().
11 */
12 function webform_schema() {
13 $schema = array();
14
15 $schema['webform'] = array(
16 'description' => 'Table for storing additional properties for webform nodes.',
17 'fields' => array(
18 'nid' => array(
19 'description' => 'The node identifier of a webform.',
20 'type' => 'int',
21 'unsigned' => TRUE,
22 'not null' => TRUE,
23 ),
24 'confirmation' => array(
25 'description' => 'The confirmation message or URL displayed to the user after submitting a form.',
26 'type' => 'text',
27 'not null' => TRUE,
28 ),
29 'confirmation_format' => array(
30 'description' => 'The input format used by the confirmation message.',
31 'type' => 'int',
32 'not null' => TRUE,
33 'default' => 0,
34 ),
35 'teaser' => array(
36 'description' => 'Boolean value for whether the entire form should be displayed on the teaser.',
37 'type' => 'int',
38 'size' => 'tiny',
39 'not null' => TRUE,
40 'default' => 0,
41 ),
42 'submit_notice' => array(
43 'description' => 'Boolean value for whether to show or hide the previous submissions notification.',
44 'type' => 'int',
45 'size' => 'tiny',
46 'not null' => TRUE,
47 'default' => 0,
48 ),
49 'submit_text' => array(
50 'description' => 'The title of the submit button on the form.',
51 'type' => 'varchar',
52 'length' => 255,
53 ),
54 'submit_limit' => array(
55 'description' => 'The number of submissions a single user is allowed to submit within an interval. -1 is unlimited.',
56 'type' => 'int',
57 'size' => 'tiny',
58 'not null' => TRUE,
59 'default' => -1,
60 ),
61 'submit_interval' => array(
62 'description' => 'The amount of time in seconds that must pass before a user can submit another submission within the set limit.',
63 'type' => 'int',
64 'not null' => TRUE,
65 'default' => -1,
66 ),
67 'additional_validate' => array(
68 'description' => 'PHP code for additional functionality when validating a form.',
69 'type' => 'text',
70 'not null' => TRUE,
71 ),
72 'additional_submit' => array(
73 'description' => 'PHP code for additional functionality when submitting a form.',
74 'type' => 'text',
75 'not null' => TRUE,
76 ),
77 ),
78 'primary key' => array('nid'),
79 );
80
81 $schema['webform_component'] = array(
82 'description' => 'Stores information about components for webform nodes.',
83 'fields' => array(
84 'nid' => array(
85 'description' => 'The node identifier of a webform.',
86 'type' => 'int',
87 'unsigned' => TRUE,
88 'not null' => TRUE,
89 'default' => 0,
90 ),
91 'cid' => array(
92 'description' => 'The identifier for this component within this node, starts at 0 for each node.',
93 'type' => 'int',
94 'size' => 'small',
95 'unsigned' => TRUE,
96 'not null' => TRUE,
97 'default' => 0,
98 ),
99 'pid' => array(
100 'description' => 'If this component has a parent fieldset, the cid of that component.',
101 'type' => 'int',
102 'size' => 'small',
103 'unsigned' => TRUE,
104 'not null' => TRUE,
105 'default' => 0,
106 ),
107 'form_key' => array(
108 'description' => 'When the form is displayed and processed, this key can be used to reference the results.',
109 'type' => 'varchar',
110 'length' => 128,
111 ),
112 'name' => array(
113 'description' => 'The label for this component.',
114 'type' => 'varchar',
115 'length' => 255,
116 ),
117 'type' => array(
118 'description' => 'The field type of this component (textfield, select, hidden, etc.).',
119 'type' => 'varchar',
120 'length' => 16,
121 ),
122 'value' => array(
123 'description' => 'The default value of the component when displayed to the end-user.',
124 'type' => 'text',
125 'not null' => TRUE,
126 ),
127 'extra' => array(
128 'description' => 'Additional information unique to the display or processing of this component.',
129 'type' => 'text',
130 'not null' => TRUE,
131 ),
132 'mandatory' => array(
133 'description' => 'Boolean flag for if this component is required.',
134 'type' => 'int',
135 'size' => 'tiny',
136 'not null' => TRUE,
137 'default' => 0,
138 ),
139 'email' => array(
140 'description' => 'Boolean flag for if submitted values for this component will be included in sent e-mails.',
141 'type' => 'int',
142 'size' => 'tiny',
143 'not null' => TRUE,
144 'default' => 0,
145 ),
146 'weight' => array(
147 'description' => 'Determines the position of this component in the form.',
148 'type' => 'int',
149 'size' => 'small',
150 'not null' => TRUE,
151 'default' => 0,
152 ),
153 ),
154 'primary key' => array('nid', 'cid'),
155 );
156
157 $schema['webform_emails'] = array(
158 'description' => 'Holds information regarding e-mails that should be sent upon submitting a webform',
159 'fields' => array(
160 'nid' => array(
161 'description' => 'The node identifier of a webform.',
162 'type' => 'int',
163 'unsigned' => TRUE,
164 'not null' => TRUE,
165 'default' => 0,
166 ),
167 'eid' => array(
168 'description' => 'The e-mail identifier for this row\'s settings.',
169 'type' => 'int',
170 'unsigned' => TRUE,
171 'size' => 'small',
172 'not null' => TRUE,
173 'default' => 0,
174 ),
175 'email' => array(
176 '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.',
177 'type' => 'text',
178 'not null' => FALSE,
179 ),
180 'subject' => array(
181 '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.',
182 'type' => 'varchar',
183 'length' => '255',
184 'not null' => FALSE,
185 ),
186 'from_name' => array(
187 '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.',
188 'type' => 'varchar',
189 'length' => '255',
190 'not null' => FALSE,
191 ),
192 'from_address' => array(
193 '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.',
194 'type' => 'varchar',
195 'length' => '255',
196 'not null' => FALSE,
197 ),
198 'template' => array(
199 '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.',
200 'type' => 'text',
201 'not null' => FALSE,
202 )
203 ),
204 'primary key' => array('nid', 'eid'),
205 );
206
207 $schema['webform_roles'] = array(
208 '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.',
209 'fields' => array(
210 'nid' => array(
211 'description' => 'The node identifier of a webform.',
212 'type' => 'int',
213 'unsigned' => TRUE,
214 'not null' => TRUE,
215 'default' => 0,
216 ),
217 'rid' => array(
218 'description' => 'The role identifier.',
219 'type' => 'int',
220 'unsigned' => TRUE,
221 'not null' => TRUE,
222 'default' => 0,
223 ),
224 ),
225 'primary key' => array('nid', 'rid'),
226 );
227
228 $schema['webform_submissions'] = array(
229 'description' => 'Holds general information about submissions outside of field values.',
230 'fields' => array(
231 'sid' => array(
232 'description' => 'The unique identifier for this submission.',
233 'type' => 'serial',
234 'unsigned' => TRUE,
235 'not null' => TRUE,
236 ),
237 'nid' => array(
238 'description' => 'The node identifier of a webform.',
239 'type' => 'int',
240 'unsigned' => TRUE,
241 'not null' => TRUE,
242 'default' => 0,
243 ),
244 'uid' => array(
245 'description' => 'The id of the user that completed this submission.',
246 'type' => 'int',
247 'unsigned' => TRUE,
248 'not null' => TRUE,
249 'default' => 0,
250 ),
251 'submitted' => array(
252 'description' => 'Timestamp of when the form was submitted.',
253 'type' => 'int',
254 'not null' => TRUE,
255 'default' => 0,
256 ),
257 'remote_addr' => array(
258 'description' => 'The IP address of the user that submitted the form.',
259 'type' => 'varchar',
260 'length' => 128,
261 ),
262 ),
263 'unique keys' => array(
264 'sid_nid' => array('sid', 'nid'),
265 ),
266 'primary key' => array('sid'),
267 );
268
269 $schema['webform_submitted_data'] = array(
270 'description' => 'Stores all submitted field data for webform submissions.',
271 'fields' => array(
272 'nid' => array(
273 'description' => 'The node identifier of a webform.',
274 'type' => 'int',
275 'unsigned' => TRUE,
276 'not null' => TRUE,
277 'default' => 0,
278 ),
279 'sid' => array(
280 'description' => 'The unique identifier for this submission.',
281 'type' => 'int',
282 'unsigned' => TRUE,
283 'not null' => TRUE,
284 'default' => 0,
285 ),
286 'cid' => array(
287 'description' => 'The identifier for this component within this node, starts at 0 for each node.',
288 'type' => 'int',
289 'size' => 'small',
290 'unsigned' => TRUE,
291 'not null' => TRUE,
292 'default' => 0,
293 ),
294 'no' => array(
295 '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.',
296 'type' => 'int',
297 'size' => 'tiny',
298 'unsigned' => TRUE,
299 'not null' => TRUE,
300 'default' => 0,
301 ),
302 'data' => array(
303 'description' => 'The submitted value of this field, may be serialized for some components.',
304 'type' => 'text',
305 'size' => 'medium',
306 'not null' => TRUE,
307 ),
308 ),
309 'indexes' => array(
310 'nid' => array('nid'),
311 'sid_nid' => array('sid', 'nid'),
312 ),
313 'primary key' => array('nid', 'sid', 'cid', 'no'),
314 );
315
316 return $schema;
317 }
318
319 /**
320 * Implementation of hook_install().
321 */
322 function webform_install() {
323 db_query("UPDATE {system} SET weight = -1 WHERE name='webform' AND type='module'");
324 drupal_install_schema('webform');
325 }
326
327 /**
328 * Implementation of hook_uninstall().
329 */
330 function webform_uninstall() {
331 // Unset webform variables.
332 variable_del('webform_use_cookies');
333 variable_del('webform_debug');
334 variable_del('webform_enable_fieldset');
335 variable_del('webform_default_from_address');
336 variable_del('webform_default_from_name');
337 variable_del('webform_default_subject');
338 variable_del('webform_csv_delimiter');
339
340 $component_list = array();
341 $path = drupal_get_path('module', 'webform') .'/components';
342 $files = file_scan_directory($path, '^.*\.inc$');
343 foreach ($files as $filename => $file) {
344 variable_del('webform_enable_'. $file->name, 1);
345 }
346
347 // Delete uploaded files.
348 $filepath = file_create_path('webform');
349 _webform_recursive_delete($filepath);
350
351 // Drop tables.
352 drupal_uninstall_schema('webform');
353 }
354
355 /**
356 * Schema changes include component id's (cid) keys in the webform_component
357 * and webform_submitted_data tables.
358 */
359 function webform_update_1() {
360
361 $ret = array();
362
363 // Start the normal update.
364 $ret[] = update_sql('CREATE TABLE {webform_tmp} ( '.
365 " nid int(10) unsigned NOT NULL default '0', ".
366 " sid int(10) unsigned NOT NULL default '0', ".
367 " cid int(10) unsigned NOT NULL default '0', ".
368 " no int(10) unsigned NOT NULL default '0', ".
369 ' data longtext, '.
370 ' PRIMARY KEY (nid, sid, cid, no) '.
371 ')');
372 $result = db_query('SELECT ws.nid, ws.sid, wc.cid, ws.name, ws.data '.
373 ' FROM {webform_submitted_data} ws, {webform_component} wc '.
374 ' WHERE ws.nid = wc.nid '.
375 ' AND ws.name = wc.name ');
376
377 while ($row = db_fetch_object($result)) {
378 $data = unserialize($row->data);
379 if ( is_array($data) ) {
380 foreach ($data as $k => $v) {
381 db_query("INSERT INTO {webform_tmp} (nid, sid, cid, no, data) VALUES (%d, %d, %d, %d, '%s')", $row->nid, $row->sid, $row->cid, $k, $v);
382 }
383 }
384 else {
385 db_query("INSERT INTO {webform_tmp} (nid, sid, cid, no, data) VALUES (%d, %d, %d, %d, '%s')", $row->nid, $row->sid, $row->cid, 0, $row->data);
386 }
387 }
388
389 $ret[] = update_sql('DROP TABLE {webform_submitted_data}');
390 $ret[] = update_sql('ALTER TABLE {webform_tmp} RENAME TO {webform_submitted_data}');
391
392 $ret[] = update_sql('CREATE TABLE {webform_submissions} ( '.
393 " nid int(10) unsigned NOT NULL default '0', ".
394 " sid int(10) unsigned NOT NULL default '0', ".
395 " submitted int(11) NOT NULL default '0', ".
396 ' PRIMARY KEY (nid, sid) '.
397 ')');
398
399 return $ret;
400 }
401
402 /**
403 * Schema changes 2: Added redirect_post column in webform table.
404 */
405 function webform_update_2() {
406
407 $ret = array();
408
409 switch ($GLOBALS['db_type']) {
410 case 'pgsql':
411 $ret[] = update_sql("ALTER TABLE {webform} ADD redirect_post int(1) UNSIGNED NOT NULL DEFAULT '0'");
412 break;
413 case 'mysqli':
414 case 'mysql':
415 $ret[] = update_sql("ALTER TABLE {webform} ADD redirect_post int(1) UNSIGNED NOT NULL DEFAULT '0' AFTER confirmation");
416 break;
417 }
418
419 return $ret;
420 }
421
422
423 /**
424 * Schema change 3: Update to UTF8
425 */
426 function webform_update_3() {
427 return _system_update_utf8(array('webform', 'webform_component', 'webform_role_node', 'webform_submissions', 'webform_submitted_data'));
428 }
429
430 /**
431 * Schema change 4: Remove the webform_role_node table, node access can be handled by other modules made for this purpose.
432 * Add additional columns to webform_submissions for recording of repeated submissions (IP Address, Browser, etc).
433 * Add additional columns to webform for setting submission limitations
434 * Change 'maintain webforms' permission into two seperate perms: 'edit webforms', 'access webform results'
435 */
436 function webform_update_4() {
437 $ret[] = update_sql('DROP TABLE if exists {webform_role_node}');
438 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD user varchar(128) AFTER submitted');
439 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD remote_addr varchar(128) AFTER user');
440 $ret[] = update_sql("ALTER TABLE {webform} ADD submit_limit int(2) NOT NULL DEFAULT '-1' AFTER redirect_post");
441 $ret[] = update_sql("ALTER TABLE {webform} ADD submit_interval int(10) NOT NULL DEFAULT '157784630' AFTER submit_limit"); // 5 years in seconds.
442
443 // Split 'maintain webforms' permissions into both 'edit webforms' and 'access webform results'.
444 $result = db_query('SELECT rid, perm FROM {permission}');
445 while ($row = db_fetch_object($result)) {
446 if (strpos($row->perm, 'maintain webforms') !== FALSE) {
447 $updated_perm = str_replace('maintain webforms', 'edit webforms, access webform results', $row->perm);
448 $ret[] = update_sql("UPDATE {permission} SET perm = '%s' WHERE rid = %d", $updated_perm, $row->rid);
449 }
450 }
451 return $ret;
452 }
453
454 /**
455 * Update MySQL sequence name to be cross-database compatible.
456 */
457 function webform_update_5() {
458 $ret = array();
459
460 switch ($GLOBALS['db_type']) {
461 case 'mysqli':
462 case 'mysql':
463 db_query('LOCK TABLES {sequences} WRITE');
464 $ret[] = update_sql(sprintf("UPDATE {sequences} SET name = '%s' WHERE name = '%s'", db_prefix_tables('{webform_submissions}_sid'), db_prefix_tables('{webform_submissions}_id')));
465 db_query('UNLOCK TABLES');
466 break;
467 }
468
469 return $ret;
470 }
471
472 /**
473 * Add a parent ID to all components, allowing nested fieldsets.
474 */
475 function webform_update_6() {
476 $ret = array();
477
478 switch ($GLOBALS['db_type']) {
479 case 'pgsql':
480 $ret[] = update_sql("ALTER TABLE {webform_component} ADD pid integer NOT NULL DEFAULT '0'");
481 break;
482 case 'mysqli':
483 case 'mysql':
484 $ret[] = update_sql('ALTER TABLE {webform_component} ADD pid int(10) NOT NULL DEFAULT 0 AFTER cid');
485 break;
486 }
487
488 return $ret;
489 }
490
491 /**
492 * Allow much larger default values for components.
493 */
494 function webform_update_7() {
495 $ret = array();
496
497 switch ($GLOBALS['db_type']) {
498 case 'pgsql':
499 db_change_column($ret, 'webform_component', 'value', 'value', 'TEXT', array('not null' => FALSE, 'default' => 'NULL'));
500 break;
501 case 'mysqli':
502 case 'mysql':
503 $ret[] = update_sql('ALTER TABLE {webform_component} CHANGE value value TEXT NULL DEFAULT NULL');
504 break;
505 }
506
507 return $ret;
508 }
509
510 /**
511 * Add additional validate and submit processing columns.
512 */
513 function webform_update_8() {
514 $ret = array();
515
516 switch ($GLOBALS['db_type']) {
517 case 'pgsql':
518 $ret[] = update_sql('ALTER TABLE {webform} ADD additional_validate text DEFAULT NULL');
519 $ret[] = update_sql('ALTER TABLE {webform} ADD additional_submit text DEFAULT NULL');
520 break;
521 case 'mysqli':
522 case 'mysql':
523 $ret[] = update_sql('ALTER TABLE {webform} ADD additional_validate text DEFAULT NULL AFTER email_subject');
524 $ret[] = update_sql('ALTER TABLE {webform} ADD additional_submit text DEFAULT NULL AFTER additional_validate');
525 break;
526 }
527
528 return $ret;
529 }
530
531 /**
532 * Remove webform version variable, now obsolete with schema and version numbers.
533 * Split columns for email_from into email_from_address and email_from_name
534 */
535 function webform_update_9() {
536 variable_del('webform_version');
537
538 $ret = array();
539
540 switch ($GLOBALS['db_type']) {
541 case 'pgsql':
542 db_change_column($ret, 'webform', 'email_from', 'email_from_address', 'varchar(255)', array('not null' => FALSE, 'default' => 'NULL'));
543 $ret[] = update_sql('ALTER TABLE {webform} ADD email_from_name varchar(255) NULL DEFAULT NULL');
544 break;
545 case 'mysqli':
546 case 'mysql':
547 $ret[] = update_sql('ALTER TABLE {webform} CHANGE email_from email_from_address varchar(255) NULL DEFAULT NULL');
548 $ret[] = update_sql('ALTER TABLE {webform} ADD email_from_name varchar(255) NULL DEFAULT NULL AFTER email');
549 break;
550 }
551
552 return $ret;
553 }
554
555 /**
556 * Add the form_key column to the webform_component table.
557 */
558 function webform_update_10() {
559 $ret = array();
560
561 switch ($GLOBALS['db_type']) {
562 case 'pgsql':
563 $ret[] = update_sql('ALTER TABLE {webform_component} ADD form_key varchar(128) NULL DEFAULT NULL');
564 break;
565
566 case 'mysqli':
567 case 'mysql':
568 $ret[] = update_sql('ALTER TABLE {webform_component} ADD form_key varchar(128) NULL DEFAULT NULL AFTER pid');
569 break;
570 }
571
572 return $ret;
573 }
574
575 /**
576 * Add unique indexes on Submission IDs for faster joins.
577 */
578 function webform_update_11() {
579 $ret = array();
580
581 switch ($GLOBALS['db_type']) {
582 case 'mysqli':
583 case 'mysql':
584 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD INDEX sid (sid)');
585 $ret[] = update_sql('ALTER TABLE {webform_submitted_data} ADD INDEX sid (sid)');
586 break;
587 case 'pgsql':
588 $ret[] = update_sql('CREATE INDEX {webform_submissions}_sid_idx ON {webform_submissions} (sid)');
589 $ret[] = update_sql('CREATE INDEX {webform_submitted_data}_sid_idx ON {webform_submitted_data} (sid)');
590 break;
591 }
592
593 return $ret;
594 }
595
596 /**
597 * Change 'user' column to 'uid' in webform_submissions table.
598 */
599 function webform_update_12() {
600 $ret = array();
601
602 switch ($GLOBALS['db_type']) {
603 case 'mysql':
604 case 'mysqli':
605 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD uid int(10) NOT NULL DEFAULT 0 AFTER sid');
606 $ret[] = update_sql('UPDATE {webform_submissions} ws set uid = (SELECT uid FROM {users} u WHERE u.name = ws.user)');
607 $ret[] = update_sql('ALTER TABLE {webform_submissions} DROP user');
608 break;
609 case 'pgsql':
610 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD uid integer NOT NULL DEFAULT 0');
611 $ret[] = update_sql('UPDATE {webform_submissions} ws set uid = (SELECT uid FROM {users} u WHERE u.name = ws.user)');
612 $ret[] = update_sql('ALTER TABLE {webform_submissions} DROP user');
613 break;
614 }
615
616 return $ret;
617 }
618
619 /**
620 * Update to the 2.x version of webform.
621 */
622 function webform_update_13() {
623 $ret = array();
624
625 // Set the webform weight to -1. This is needed to have webform's hook_menu()
626 // take precedence over node_menu().
627 $ret[] = update_sql("UPDATE {system} SET weight = -1 WHERE type = 'module' and name = 'webform'");
628
629 // Ensure crufty submission data that was not removed when webform nodes
630 // were deleted is cleared out before doing key changes.
631 $ret[] = update_sql("DELETE FROM {webform} WHERE nid NOT IN (SELECT nid FROM {node} WHERE type = 'webform')");
632 $ret[] = update_sql("DELETE FROM {webform_component} WHERE nid NOT IN (SELECT nid FROM {node} WHERE type = 'webform')");
633 $ret[] = update_sql("DELETE FROM {webform_submissions} WHERE nid NOT IN (SELECT nid FROM {node} WHERE type = 'webform')");
634 $ret[] = update_sql("DELETE FROM {webform_submitted_data} WHERE nid NOT IN (SELECT nid FROM {node} WHERE type = 'webform')");
635 $result = db_query('SELECT nid FROM {webform}');
636 while ($row = db_fetch_object($result)) {
637 db_query("DELETE FROM {webform_submitted_data} WHERE nid = %d AND cid NOT IN (SELECT cid FROM {webform_component} c WHERE c.nid = %d)", $row->nid, $row->nid);
638 }
639
640 // Convert timestamp-based cids to small integers starting at 1 for each node.
641 $result = db_query('SELECT nid, cid FROM {webform_component} ORDER BY nid ASC, cid ASC');
642 $nid = 0;
643 while ($component = db_fetch_array($result)) {
644 if ($component['nid'] != $nid) {
645 $nid = $component['nid'];
646 $cid = 1;
647 }
648 $ret[] = update_sql('UPDATE {webform_component} SET cid = '. $cid .' WHERE nid = '. $nid .' AND cid = '. $component['cid']);
649 $ret[] = update_sql('UPDATE {webform_component} SET pid = '. $cid .' WHERE nid = '. $nid .' AND pid = '. $component['cid']);
650 $ret[] = update_sql('UPDATE {webform_submitted_data} SET cid = '. $cid .' WHERE nid = '. $nid .' AND cid = '. $component['cid']);
651 $cid++;
652 }
653
654 // Convert the cid and pid columns to smallints for efficiency.
655 switch ($GLOBALS['db_type']) {
656 case 'mysqli':
657 case 'mysql':
658 $ret[] = update_sql("ALTER TABLE {webform_component} CHANGE cid cid smallint unsigned NOT NULL default '0'");
659 $ret[] = update_sql("ALTER TABLE {webform_component} CHANGE pid pid smallint unsigned NOT NULL default '0'");
660 $ret[] = update_sql("ALTER TABLE {webform_submitted_data} CHANGE cid cid smallint unsigned NOT NULL default '0'");
661 break;
662 case 'pgsql':
663 db_change_column($ret, 'webform_component', 'cid', 'cid', 'smallint', array('not null' => TRUE, 'default' => '0'));
664 db_change_column($ret, 'webform_component', 'pid', 'pid', 'smallint', array('not null' => TRUE, 'default' => '0'));
665 db_change_column($ret, 'webform_submitted_data', 'cid', 'cid', 'smallint', array('not null' => TRUE, 'default' => '0'));
666 break;
667 }
668 return $ret;
669 }
670
671 /**
672 * Variable name changes.
673 */
674 function webform_update_14() {
675 $ret = array();
676 variable_set('webform_default_from_address', variable_get('webform_default_from_email', variable_get('site_mail', ini_get('sendmail_from'))));
677 variable_del('webform_default_from_email');
678
679 if ('Form submission from: ' == variable_get('webform_default_subject', 'Form submission from: ')) {
680 variable_set('webform_default_subject', 'Form submission from: %title');
681 }
682 return $ret;
683 }
684
685 /**
686 * Convert 'CC' option in extra column to simply 'email'.
687 * Set email value to '%useremail' instead of 'user email'.
688 * Change the 'disabled' option from an attributes option to an individual option.
689 */
690 function webform_update_15() {
691 $ret = array();
692 $result = db_query("SELECT nid, cid, extra, value FROM {webform_component} WHERE type = 'email'");
693 while ($row = db_fetch_array($result)) {
694 $extra = unserialize($row['extra']);
695 if ($extra['carboncopy']) {
696 $extra['email'] = 1;
697 unset($extra['carboncopy']);
698 }
699 $value = $row['value'] == 'user email' ? '%useremail' : '';
700 db_query("UPDATE {webform_component} SET extra = '%s', value = '%s' WHERE nid = %d and cid = %d", serialize($extra), $value, $row['nid'], $row['cid']);
701 }
702
703 $result = db_query("SELECT nid, cid, extra FROM {webform_component} WHERE type IN ('email', 'textfield', 'textarea')");
704 while ($row = db_fetch_array($result)) {
705 $extra = unserialize($row['extra']);
706 if ($extra['attributes']['disabled']) {
707 $extra['disabled'] = 1;
708 unset($extra['attributes']['disabled']);
709 db_query("UPDATE {webform_component} SET extra = '%s' WHERE nid = %d and cid = %d", serialize($extra), $row['nid'], $row['cid']);
710 }
711 }
712 return $ret;
713 }
714
715 /**
716 * Add the submit button text and teaser columns. Remove redirect_post.
717 */
718 function webform_update_16() {
719 $ret = array();
720
721 switch ($GLOBALS['db_type']) {
722 case 'mysqli':
723 case 'mysql':
724 $ret[] = update_sql('ALTER TABLE {webform} DROP redirect_post');
725 $ret[] = update_sql('ALTER TABLE {webform} ADD teaser tinyint NOT NULL DEFAULT 0 AFTER confirmation');
726 $ret[] = update_sql('ALTER TABLE {webform} ADD submit_text varchar(255) NULL DEFAULT NULL AFTER teaser');
727 break;
728 case 'pgsql':
729 $ret[] = update_sql('ALTER TABLE {webform} DROP redirect_post');
730 $ret[] = update_sql('ALTER TABLE {webform} ADD teaser smallint NOT NULL DEFAULT 0');
731 $ret[] = update_sql('ALTER TABLE {webform} ADD submit_text varchar(255) NULL DEFAULT NULL');
732 break;
733 }
734
735 return $ret;
736 }
737
738 /**
739 * Set the submit interval to a real "unlimited" value instead of 5 years.
740 */
741 function webform_update_17() {
742 $ret = array();
743 $ret[] = update_sql('UPDATE {webform} SET submit_interval = -1 WHERE submit_interval = 157784630');
744 return $ret;
745 }
746
747 /**
748 * Convert E-mail from name, address, and subject to integer values.
749 */
750 function webform_update_18() {
751 $ret = array();
752 $result = db_query('SELECT * FROM {webform}');
753 while ($webform = db_fetch_object($result)) {
754 foreach (array('email_from_name', 'email_from_address', 'email_subject') as $key) {
755 if ($webform->{$key} == 'Automatic' || $webform->{$key} == 'Default') {
756 $ret[] = update_sql('UPDATE {webform} SET '. $key ." = 'default' WHERE nid = ". $webform->nid);
757 }
758 elseif (!is_numeric($webform->{$key})) {
759 $cid = db_result(db_query("SELECT cid FROM {webform_component} WHERE name = '%s' AND nid = %d", $webform->{$key}, $webform->nid));
760 if ($cid) {
761 $ret[] = update_sql('UPDATE {webform} SET '. $key ." = '". $cid ."' WHERE nid = ". $webform->nid);
762 }
763 }
764 }
765 }
766 return $ret;
767 }
768
769
770 /**
771 * Upgrade hook to remove the captcha component.
772 */
773 function webform_update_19() {
774 $ret = array();
775 variable_del('webform_enable_captcha');
776
777 // Check for the new version of captcha module.
778 if ($GLOBALS['db_type'] == 'pgsql') {
779 $captcha_exists = db_result(db_query("SELECT table_name FROM {information_schema.tables} WHERE table_schema = 'public' AND table_name LIKE 'captcha_points'"));
780 }
781 else {
782 $captcha_exists = db_result(db_query("SHOW TABLES LIKE 'captcha_points'"));
783 }
784
785 if (module_exists('image_captcha')) {
786 $captcha_module = 'image_captcha';
787 $captcha_type = 'Image';
788 }
789 else {
790 $captcha_module = 'captcha';
791 $captcha_type = 'Math';
792 }
793
794 $result = db_query("SELECT nid, cid FROM {webform_component} WHERE type = 'captcha'");
795 while ($component = db_fetch_object($result)) {
796 $ret[] = update_sql('DELETE FROM {webform_component} WHERE cid = '. $component->cid .' AND nid = '. $component->nid);
797 if ($captcha_exists) {
798 $added = db_result(db_query("SELECT form_id FROM {captcha_points} WHERE form_id = 'webform_client_form_". $component->nid ."'"));
799 if (!$added) {
800 $ret[] = update_sql("INSERT INTO {captcha_points} (form_id, module, type) VALUES ('webform_client_form_". $component->nid ."', '". $captcha_module ."', '". $captcha_type ."')");
801 }
802 }
803 }
804 return $ret;
805 }
806
807 /**
808 * Set new primary keys for the submissions table.
809 */
810 function webform_update_20() {
811 $ret = array();
812 switch ($GLOBALS['db_type']) {
813 case 'mysqli':
814 case 'mysql':
815 // Update the webform_submissions table with sid primary key instead of nid, sid.
816 $ret[] = update_sql('ALTER TABLE {webform_submissions} DROP INDEX sid');
817 $ret[] = update_sql('ALTER TABLE {webform_submissions} DROP PRIMARY KEY');
818 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD UNIQUE INDEX sid_nid (sid, nid)');
819 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD PRIMARY KEY (sid)');
820
821 // Update webform_submitted_data table removing nid from the primary key.
822 $ret[] = update_sql('ALTER TABLE {webform_submitted_data} DROP PRIMARY KEY');
823 $ret[] = update_sql('ALTER TABLE {webform_submitted_data} DROP INDEX sid');
824 // While we've got these keys removed, decrease the size of the 'no' column.
825 $ret[] = update_sql('ALTER TABLE {webform_submitted_data} CHANGE no no tinyint NOT NULL DEFAULT 0');
826 $ret[] = update_sql('ALTER TABLE {webform_submitted_data} ADD PRIMARY KEY (sid, cid, no)');
827 $ret[] = update_sql('ALTER TABLE {webform_submitted_data} ADD INDEX nid (nid)');
828 $ret[] = update_sql('ALTER TABLE {webform_submitted_data} ADD INDEX sid_nid (sid, nid)');
829 break;
830 case 'pgsql':
831 $ret[] = update_sql('ALTER TABLE {webform_submissions} DROP CONSTRAINT {webform_submissions}_pkey');
832 $ret[] = update_sql('DROP INDEX {webform_submissions}_sid_idx');
833 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD PRIMARY KEY (sid)');
834 $ret[] = update_sql('ALTER TABLE {webform_submissions} ADD CONSTRAINT {webform_submissions}_sid_nid_key UNIQUE (sid, nid)');
835
836 $ret[] = update_sql('DROP INDEX {webform_submitted_data}_sid_idx');
837 db_change_column($ret, 'webform_submitted_data', 'no', 'no', 'smallint', array('not null' => TRUE, 'default' => '0'));
838 $ret[] = update_sql('ALTER TABLE {webform_submitted_data} ADD PRIMARY KEY (sid, cid, no)');
839 $ret[] = update_sql('CREATE INDEX {webform_submitted_data}_nid_idx ON {webform_submitted_data} (nid)');
840 $ret[] = update_sql('CREATE INDEX {webform_submitted_data}_sid_nid_idx ON {webform_submitted_data} (sid, nid)');
841
842 $ret[] = update_sql('ALTER TABLE {webform_component} ADD PRIMARY KEY (nid, cid)');
843 break;
844 }
845 return $ret;
846 }
847
848 /**
849 * Set the upgrade
850 */
851
852 /**
853 * Upgrade to Drupal 6. Convert submissions sid column to auto-increment.
854 */
855 function webform_update_6001() {
856 $ret = array();
857 // Keys must be dropped before altering the column.
858 db_drop_primary_key($ret, 'webform_submissions');
859 db_drop_unique_key($ret, 'webform_submissions', 'sid_nid');
860
861 // Alter to a primary key and add the unique key back.
862 db_change_field($ret, 'webform_submissions', 'sid', 'sid', array('type' => 'serial', 'not null' => TRUE), array('primary key' => array('sid')));
863 db_add_unique_key($ret, 'webform_submissions', 'sid_nid', array('sid', 'nid'));
864 return $ret;
865 }
866
867 /**
868 * Increase the size of the component instance name.
869 */
870 function webform_update_6200() {
871 $ret = array();
872 db_change_field($ret, 'webform_component', 'name', 'name', array('type' => 'varchar', 'length' => 255, 'default' => 'NULL'));
873 return $ret;
874 }
875
876 /**
877 * Add a column for email to the webform_component table.
878 */
879 function webform_update_6201() {
880 $ret = array();
881
882 // This update will already be run as webform_update_5201 on Drupal 5.
883 if (db_column_exists('webform_component', 'email')) {
884 return $ret;
885 }
886
887 db_add_field($ret, 'webform_component', 'email', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
888 $ret[] = update_sql('UPDATE {webform_component} SET email = 1');
889
890 return $ret;
891 }
892
893 /**
894 * Per-webform submission access control based on roles.
895 */
896 function webform_update_6202() {
897 $ret = array();
898
899 // This update will already be run as webform_update_5202 on Drupal 5.
900 if (db_table_exists('webform_roles')) {
901 return $ret;
902 }
903
904 db_create_table($ret, 'webform_roles', array(
905 '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.',
906 'fields' => array(
907 'nid' => array(
908 'description' => 'The node identifier of a webform.',
909 'type' => 'int',
910 'unsigned' => TRUE,
911 'not null' => TRUE,
912 'default' => 0,
913 ),
914 'rid' => array(
915 'description' => 'The role identifier.',
916 'type' => 'int',
917 'unsigned' => TRUE,
918 'not null' => TRUE,
919 'default' => 0,
920 ),
921 ),
922 'primary key' => array('nid', 'rid'),
923 ));
924
925 $result = db_query("SELECT nid FROM {node} WHERE type = 'webform'");
926 while ($node = db_fetch_object($result)) {
927 db_query("INSERT INTO {webform_roles} (nid, rid) VALUES (%d, 1)", $node->nid);
928 db_query("INSERT INTO {webform_roles} (nid, rid) VALUES (%d, 2)", $node->nid);
929 }
930
931 return $ret;
932 }
933
934 /**
935 * Cleanup filtering values used by the file component.
936 *
937 * Previously, file extensions were saved by category, exactly as the FormAPI
938 * returned to the submit handler. All extensions are now stored in a single
939 * array, including only valid extensions.
940 */
941 function webform_update_6203() {
942 $ret = array();
943
944 // This update will already be run as webform_update_5203 on Drupal 5.
945
946 $result = db_query("SELECT nid, cid, extra FROM {webform_component} WHERE type = 'file'");
947 while ($component = db_fetch_object($result)) {
948 $extra = unserialize($component->extra);
949 $extensions = array();
950
951 // Sanity check, set some defaults if no filtering is in place.
952 if (!isset($extra['filtering']['types'])) {
953 $extra['filtering']['types'] = array(
954 'webimages' => drupal_map_assoc(array('png', 'gif', 'jpg')),
955 );
956 }
957 // Or if filtering has already been updated, skip this update.
958 elseif (!isset($extra['filtering']['types']['webimages'])) {
959 continue;
960 }
961
962 // Defined types.
963 foreach ($extra['filtering']['types'] as $category => $category_extensions) {
964 foreach ((array)$category_extensions as $extension) {
965 if (!is_numeric($extension)) {
966 $extensions[] = $extension;
967 }
968 }
969 }
970
971 // Additional types.
972 $additional_extensions = explode(',', $extra['filtering']['addextensions']);
973 foreach ($additional_extensions as $extension) {
974 $clean_extension = drupal_strtolower(trim($extension));
975 if (!empty($clean_extension) && !in_array($clean_extension, $extensions)) {
976 $extensions[] = $clean_extension;
977 }
978 }
979
980 $extra['filtering']['types'] = $extensions;
981 db_query("UPDATE {webform_component} SET extra = '%s' WHERE nid = %d AND cid = %d", serialize($extra), $component->nid, $component->cid);
982 }
983
984 return $ret;
985 }
986
987 /**
988 * Set all files to permanent status uploaded by Webform.
989 */
990 function webform_update_6204() {
991 $ret = array();
992 $ret[] = update_sql("UPDATE {files} SET status = 1 WHERE filepath LIKE '". file_directory_path() ."/webform/%'");
993 return $ret;
994 }
995
996 /**
997 * Schema fixes to make Drupal 5 upgrades identical to clean Drupal 6 installs.
998 */
999 function webform_update_6205() {
1000 $ret = array();
1001
1002 // Remove disp-width and default from webform.nid.
1003 db_drop_primary_key($ret, 'webform');
1004 db_change_field($ret, 'webform', 'nid', 'nid', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), array('primary key' => array('nid')));
1005
1006 // Set not null property on webform.confirmation.
1007 db_change_field($ret, 'webform', 'confirmation', 'confirmation', array('type' => 'text', 'not null' => TRUE));
1008
1009 // Set size to tiny, remove disp-width on webform.submit_limit.
1010 db_change_field($ret, 'webform', 'submit_limit', 'submit_limit', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => -1));
1011
1012 // Set default value to -1, remove disp-width on webform.submit_interval.
1013 db_change_field($ret, 'webform', 'submit_interval', 'submit_interval', array('type' => 'int', 'not null' => TRUE, 'default' => -1));
1014
1015 // Set not null property on webform.additional_validate.
1016 db_change_field($ret, 'webform', 'additional_validate', 'additional_validate', array('type' => 'text', 'not null' => TRUE));
1017
1018 // Set not null property on webform.additional_submit.
1019 db_change_field($ret, 'webform', 'additional_submit', 'additional_submit', array('type' => 'text', 'not null' => TRUE));
1020
1021 // Set not null property, default on webform_component.name.
1022 db_change_field($ret, 'webform_component', 'name', 'name', array('type' => 'varchar', 'length' => 255));
1023
1024 // Set not null property on webform_component.value.
1025 db_change_field($ret, 'webform_component', 'value', 'value', array('type' => 'text', 'not null' => TRUE));
1026
1027 // Set not null property on webform_component.extra.
1028 db_change_field($ret, 'webform_component', 'extra', 'extra', array('type' => 'text', 'not null' => TRUE));
1029
1030 // Set column size, disp-width on webform_component.mandatory.
1031 db_change_field($ret, 'webform_component', 'mandatory', 'mandatory', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
1032
1033 // Set column size, disp-width, not null property on webform_component.weight.
1034 db_change_field($ret, 'webform_component', 'weight', 'weight', array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' => 0));
1035
1036 // Set unsigned, not null property on webform_submissions.sid.
1037 db_drop_unique_key($ret, 'webform_submissions', 'sid_nid');
1038 db_change_field($ret, 'webform_submissions', 'sid', 'sid', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE));
1039 db_drop_primary_key($ret, 'webform_submissions');
1040 db_change_field($ret, 'webform_submissions', 'sid', 'sid', array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE), array('primary key' => array('sid'), 'unique keys' => array('sid_nid' => array('sid', 'nid'))));
1041
1042 // Temporarily drop all keys from the webform_submitted_data table for changes.
1043 db_drop_primary_key($ret, 'webform_submitted_data');
1044 db_drop_index($ret, 'webform_submitted_data', 'nid');
1045 db_drop_index($ret, 'webform_submitted_data', 'sid_nid');
1046
1047 // Set unsigned, size on webform_submitted_data.no.
1048 db_change_field($ret, 'webform_submitted_data', 'no', 'no', array('type' => 'int', 'unsigned' => TRUE, 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
1049
1050 // Set size, not null property on webform_submitted_data.data.
1051 db_change_field($ret, 'webform_submitted_data', 'data', 'data', array('type' => 'text', 'size' => 'medium', 'not null' => TRUE));
1052
1053 // Set correct keys.
1054 db_add_primary_key($ret, 'webform_submitted_data', array('nid', 'sid', 'cid', 'no'));
1055 db_add_index($ret, 'webform_submitted_data', 'nid', array('nid'));
1056 db_add_index($ret, 'webform_submitted_data', 'sid_nid', array('sid', 'nid'));
1057
1058 return $ret;
1059 }
1060
1061 /**
1062 * Add a separate column for confirmation message input format.
1063 */
1064 function webform_update_6301() {
1065 $ret = array();
1066
1067 // Safety check to prevent re-adding existing column.
1068 if (db_column_exists('webform', 'confirmation_format')) {
1069 return $ret;
1070 }
1071
1072 db_add_field($ret, 'webform', 'confirmation_format', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
1073 $result = db_query("SELECT n.nid, nr.format FROM {node} n INNER JOIN {node_revisions} nr ON n.vid = nr.vid WHERE n.type = 'webform'");
1074 while ($node = db_fetch_object($result)) {
1075 db_query('UPDATE {webform} SET confirmation_format = %d WHERE nid = %d', $node->format, $node->nid);
1076 }
1077
1078 return $ret;
1079 }
1080
1081 /**
1082 * Convert node-level e-mail settings to new webform_emails table.
1083 */
1084 function webform_update_6302() {
1085 $ret = array();
1086
1087 // Safety check to prevent recreating the webform_emails table.
1088 if (db_table_exists('webform_emails')) {
1089 return $ret;
1090 }
1091
1092 $table = array(
1093 'fields' => array(
1094 'nid' => array(
1095 'type' => 'int',
1096 'unsigned' => TRUE,
1097 'not null' => TRUE,
1098 'default' => 0,
1099 ),
1100 'eid' => array(
1101 'type' => 'int',
1102 'unsigned' => TRUE,
1103 'size' => 'small',
1104 'not null' => TRUE,
1105 'default' => 0,
1106 ),
1107 'email' => array(
1108 'type' => 'text',
1109 'not null' => FALSE,
1110 ),
1111 'subject' => array(
1112 'type' => 'varchar',
1113 'length' => '255',
1114 'not null' => FALSE,
1115 ),
1116 'from_name' => array(
1117 'type' => 'varchar',
1118 'length' => '255',
1119 'not null' => FALSE,
1120 ),
1121 'from_address' => array(
1122 'type' => 'varchar',
1123 'length' => '255',
1124 'not null' => FALSE,
1125 ),
1126 'template' => array(
1127 'type' => 'text',
1128 'not null' => FALSE,
1129 )
1130 ),
1131 'primary key' => array('nid', 'eid'),
1132 );
1133
1134 db_create_table($ret, 'webform_emails', $table);
1135
1136 // Move over data from the webform table.
1137 $result = db_query("SELECT w.nid, w.email, w.email_from_name, w.email_from_address, w.email_subject, wc.cid, wc.extra FROM {webform} w LEFT JOIN {webform_component} wc ON w.nid = wc.nid AND type IN ('select', 'hidden', 'email') ORDER BY nid");
1138 $nid = 0;
1139 while ($row = db_fetch_object($result)) {
1140 // Insert an e-mail settings row for the default e-mail.
1141 if ($row->nid != $nid) {
1142 $nid = $row->nid;
1143 $eid = 0;
1144 if (!empty($row->email)) {
1145 $eid++;
1146