5 * Webform module tests.
8 class WebformTestCase extends DrupalWebTestCase {
9 private $_webform_node;
10 private $_webform_components;
11 public $webform_users;
16 function setUp($added_modules = array()) {
17 // Enable Webform and Token module if available.
18 if (module_exists('token')) {
19 $modules = array('webform', 'token');
22 $modules = array('webform');
24 parent::setUp(array_merge($modules, $added_modules));
26 // Create a profile field to test [user:?] tokens.
28 'field_name' => 'gender',
33 'field_name' => 'gender',
34 'entity_type' => 'user',
38 'type' => 'text_textfield',
42 field_create_field($field);
43 field_create_instance($instance);
45 // Create a normal user that can view their own submissions.
46 $permissions['userAccess'] = array(
48 'access own webform submissions',
51 // Create a normal user than can edit their own submissions.
52 $permissions['userEdit'] = array(
54 'edit own webform submissions',
57 // Create a webform editor to test creating and editing own content.
58 $permissions['editor'] = array(
60 'create webform content',
61 'edit own webform content',
62 'access all webform results',
65 // Create a webform admin that will do all node creation.
66 $permissions['admin'] = array(
69 'create webform content',
70 'edit any webform content',
71 'access all webform results',
72 'edit all webform submissions',
73 'delete all webform submissions',
76 foreach ($permissions as $user_key => $role_permissions) {
77 $this->webform_users[$user_key] = $this->drupalCreateUser($role_permissions);
78 $this->webform_users[$user_key]->gender = array(LANGUAGE_NONE => array(array('value' => 'Female')));
79 user_save($this->webform_users[$user_key]);
84 * Implemenation of tearDown().
87 // Delete the webform admin and any created nodes.
88 foreach ($this->webform_users as $account) {
90 $result = db_select('node')
92 ->condition('uid', $uid)
94 foreach ($result as $node) {
95 node_delete($node->nid);
97 user_cancel(array(), $uid, 'user_cancel_delete');
106 function webformReset() {
107 $this->_webform_node = NULL;
108 $this->_webform_components = NULL;
112 * Provide a list of components to test throughout the suite.
114 * Each component provides:
115 * - A default configuration for the component.
116 * - Values to try setting via POST
117 * - Values that should match the database storage when set via POST
118 * - Values that should match the database storage when using the default values.
121 * An array of each component settings.
123 function testWebformComponents() {
124 if (isset($this->_webform_components)) {
125 return $this->_webform_components;
128 $this->_webform_components = array(
129 // Test date components.
131 'component' => array(
132 'form_key' => 'date',
135 'value' => '19 Nov 1978',
137 'timezone' => 'site',
138 'start_date' => '-100 years',
139 'end_date' => '+2 years',
145 'sample values' => array('day' => '30', 'month' => '9', 'year' => '1982'),
146 'database values' => array('1982-09-30'),
147 'database default values' => array('1978-11-19'),
148 // Conditionals match against the 'sample values'.
149 'match conditional values' => array(
150 'equal' => '1982/9/30',
151 'before' => '1982/10/1',
152 'before_equal' => '1982/9/30',
153 'after' => '1982/9/29',
154 'after_equal' => '1982/9/29',
156 'mismatch conditional values' => array(
157 'equal' => '1981/9/30',
158 'before' => '1982/9/30',
159 'before_equal' => '1982/9/29',
160 'after' => '1982/9/30',
161 'after_equal' => '1982/10/1',
165 // Test grid components.
167 'component' => array(
168 'form_key' => 'grid',
173 'questions' => "0|Ålphå\n1|ıé†å\n2|Î鬆å", // Left side
174 'options' => "0|øne\n1|twö\n2|ǼBƇ\n3|€Euro", // Top
180 'sample values' => array('0' => '0', '1' => '1', '2' => '2'),
181 'database values' => array('0' => '0', '1' => '1', '2' => '2'),
182 'database default values' => array('', '', ''),
184 'grid_keyed' => array(
185 'component' => array(
186 'form_key' => 'grid_keyed',
187 'name' => 'Grid Keyed',
191 'questions' => "one|What's your option?\ntwo|Agåin?\nthree|One more time!", // Left side.
192 'options' => "one|Option one\ntwo|Option 2\nthree| Three is me", // Top
198 'sample values' => array('one' => 'one', 'two' => 'two', 'three' => 'three'),
199 'database values' => array('one' => 'one', 'two' => 'two', 'three' => 'three'),
200 'database default values' => array('one' => '', 'two' => '', 'three' => ''),
203 // Test select components.
204 'checkboxes' => array(
205 'component' => array(
206 'form_key' => 'checkboxes',
207 'name' => 'Checkboxes',
211 'items' => "one|one\ntwo|two\nthree|three",
218 'sample values' => array('one' => TRUE, 'two' => FALSE, 'three' => TRUE),
219 'database values' => array('one', 'three'),
220 'database default values' => array('two'),
221 // Conditionals match against the 'sample values'.
222 'match conditional values' => array(
223 'equal' => array('one', 'three'), // ANDed together match.
224 'not_equal' => array('two'),
226 'mismatch conditional values' => array(
227 'equal' => array('one', 'two'),
228 'not_equal' => array('two', 'three'),
231 'checkboxes_zero' => array(
232 'component' => array(
233 'form_key' => 'checkboxes_zero',
234 'name' => 'Checkboxes zero',
238 'items' => "0|zero\n1|one\n2|two",
245 'sample values' => array('0' => TRUE),
246 'database values' => array('0'),
247 'database default values' => array('0'),
248 // Conditionals match against the 'sample values'.
249 'match conditional values' => array(
253 'mismatch conditional values' => array(
259 'component' => array(
260 'form_key' => 'radios',
265 'items' => "one|one\ntwo|two\nthree|three",
271 'sample values' => 'one',
272 'database values' => array('one'),
273 'database default values' => array('two'),
274 // Conditionals match against the 'sample values'.
275 'match conditional values' => array(
277 'not_equal' => 'two',
279 'mismatch conditional values' => array(
281 'not_equal' => 'one',
284 'radios_zero' => array(
285 'component' => array(
286 'form_key' => 'radios_zero',
287 'name' => 'Radios zero',
291 'items' => "0|zero\n1|one\n2|two",
297 'sample values' => '0',
298 'database values' => array('0'),
299 'database default values' => array('0'),
300 // Conditionals match against the 'sample values'.
301 'match conditional values' => array(
305 'mismatch conditional values' => array(
310 'radios_relative' => array(
311 'component' => array(
312 'form_key' => 'radios_relative',
313 'name' => 'Radios relative',
317 'items' => "zero|Zero\none|One\ntwo|Two\nthree|Three\n",
323 'sample values' => 'one',
324 'database values' => array('one'),
325 'database default values' => array('one'),
326 // Conditionals match against the 'sample values'.
327 'match conditional values' => array(
329 'not_equal' => 'zero',
330 'less_than' => 'two',
331 'less_than_equal' => 'one',
332 'greater_than' => 'zero',
333 'greater_than_equal' => 'zero',
335 'mismatch conditional values' => array(
337 'not_equal' => 'one',
338 'less_than' => 'one',
339 'less_than_equal' => 'zero',
340 'greater_than' => 'two',
341 'greater_than_equal' => 'two',
345 'component' => array(
346 'form_key' => 'select',
351 'description' => 'Description here',
352 'items' => "one|one\ntwo|two\nthree|three\nfour|four\nfive|five\nsix|six",
359 'sample values' => 'two',
360 'database values' => array('two'),
361 'database default values' => array('one'),
362 // Conditionals match against the 'sample values'.
363 'match conditional values' => array(
365 'not_equal' => 'one',
367 'mismatch conditional values' => array(
369 'not_equal' => 'two',
372 'select_zero' => array(
373 'component' => array(
374 'form_key' => 'select_zero',
375 'name' => 'Select zero',
379 'description' => 'Tests saving zero as a value.',
380 'items' => "0|zero\n1|one\n2|two",
387 'sample values' => '0',
388 'database values' => array('0'),
389 'database default values' => array('0'),
390 // Conditionals match against the 'sample values'.
391 'match conditional values' => array(
395 'mismatch conditional values' => array(
400 'select_no_default' => array(
401 'component' => array(
402 'form_key' => 'select_no_default',
403 'name' => 'Select no default',
407 'description' => 'Description here',
408 'items' => "one|one\ntwo|two\nthree|three\nfour|four\nfive|five\nsix|six",
415 'sample values' => 'two',
416 'database values' => array('two'),
417 'database default values' => array(''),
418 // Conditionals match against the 'sample values'.
419 'match conditional values' => array(
423 'mismatch conditional values' => array(
425 'not_equal' => 'two',
428 'select_no_default_zero' => array(
429 'component' => array(
430 'form_key' => 'select_no_default_zero',
431 'name' => 'Select no default zero',
435 'description' => 'Tests saving zero as a value.',
436 'items' => "0|zero\n1|one\n2|two",
443 'sample values' => '0',
444 'database values' => array('0'),
445 'database default values' => array(''),
446 // Conditionals match against the 'sample values'.
447 'match conditional values' => array(
451 'mismatch conditional values' => array(
456 'select_optgroup' => array(
457 'component' => array(
458 'form_key' => 'select_optgroup',
459 'name' => 'Select Optgroup',
461 'value' => 'option 1-2',
463 'description' => 'Tests saving zero as a value.',
464 'items' => "<Group 1>\noption 1-1|option 1-1\noption 1-2|option 1-2\noption 1-3|option 1-3\n<Group 2>\noption 2-1|option 2-1\noption 2-2|option 2-2\noption 2-3|option 2-3",
471 'sample values' => 'option 2-2',
472 'database values' => array('option 2-2'),
473 'database default values' => array('option 1-2'),
475 'select_email' => array(
476 'component' => array(
477 'form_key' => 'select_email',
478 'name' => 'Select e-mails',
480 'value' => 'nate@localhost.localhost',
482 'items' => "nate@localhost.localhost|one\nadmin@localhost.localhost|two",
488 'sample values' => 'admin@localhost.localhost',
489 'database values' => array('admin@localhost.localhost'),
490 'database default values' => array('nate@localhost.localhost'),
492 'select_multiple' => array(
493 'component' => array(
494 'form_key' => 'select_multiple',
495 'name' => 'Select Multiple',
497 'value' => 'one,two',
499 'items' => "one|one\ntwo|two\nthree|three",
507 // TODO: I'd like to test a value, but SimpleTest can't set multiple values.
508 'sample values' => NULL,
509 'database values' => array('one', 'two'),
510 'database default values' => array('one', 'two'),
512 'select_relative' => array(
513 'component' => array(
514 'form_key' => 'select_relative',
515 'name' => 'Select relative',
519 'items' => "zero|Zero\none|One\ntwo|Two\nthree|Three\n",
526 'sample values' => 'one',
527 'database values' => array('one'),
528 'database default values' => array('one'),
529 // Conditionals match against the 'sample values'.
530 'match conditional values' => array(
532 'not_equal' => 'zero',
533 'less_than' => 'two',
534 'less_than_equal' => 'one',
535 'greater_than' => 'zero',
536 'greater_than_equal' => 'zero',
538 'mismatch conditional values' => array(
540 'not_equal' => 'one',
541 'less_than' => 'one',
542 'less_than_equal' => 'zero',
543 'greater_than' => 'two',
544 'greater_than_equal' => 'two',
548 // Test date components.
549 'date_textfield' => array(
550 'component' => array(
551 'form_key' => 'date_textfield',
552 'name' => 'Date Textfield',
554 'value' => 'Nov 19 1978',
556 'timezone' => 'site',
557 'start_date' => '-100 years',
558 'end_date' => '+2 years',
559 'year_textfield' => 1,
565 'sample values' => array('day' => '30', 'month' => '9', 'year' => '1982'),
566 'database values' => array('1982-09-30'),
567 'database default values' => array('1978-11-19'),
568 // Conditionals match against the 'sample values'.
569 'match conditional values' => array(
570 'equal' => '1982/9/30',
571 'before' => '1982/10/1',
572 'before_equal' => '1982/9/30',
573 'after' => '1982/9/29',
574 'after_equal' => '1982/9/29',
576 'mismatch conditional values' => array(
577 'equal' => '1981/9/30',
578 'before' => '1982/9/30',
579 'before_equal' => '1982/9/29',
580 'after' => '1982/9/30',
581 'after_equal' => '1982/10/1',
585 // Test email components.
587 'component' => array(
588 'form_key' => 'email',
591 'value' => '[current-user:mail]',
594 // SimpleTest does not support type="email" input fields.
595 'attributes' => array('type' => 'text'),
600 'sample values' => 'admin@localhost.localhost',
601 'database values' => array('admin@localhost.localhost'),
602 'database default values' => array($this->webform_users['admin']->mail),
603 // Conditionals match against the 'sample values'.
604 'match conditional values' => array(
605 'equal' => 'admin@localhost.localhost',
607 'contains' => 'admin',
608 'does_not_contain' => 'foo',
609 'begins_with' => 'admin',
610 'ends_with' => 'localhost',
613 'mismatch conditional values' => array(
614 'equal' => 'foo@localhost.localhost',
615 'not_equal' => 'admin@localhost.localhost',
617 'does_not_contain' => 'admin',
618 'begins_with' => 'localhost',
619 'ends_with' => 'admin',
624 // Test hidden components.
626 'component' => array(
627 'form_key' => 'hidden',
630 'value' => 'default hidden value',
635 'sample values' => NULL,
636 'database values' => array('default hidden value'),
637 'database default values' => array('default hidden value'),
638 // Conditionals match against the 'sample values'.
639 'match conditional values' => array(
640 'equal' => 'default hidden value',
642 'contains' => 'hidden',
643 'does_not_contain' => 'foo',
644 'begins_with' => 'default',
645 'ends_with' => 'value',
648 'mismatch conditional values' => array(
650 'not_equal' => 'default hidden value',
652 'does_not_contain' => 'hidden',
653 'begins_with' => 'value',
654 'ends_with' => 'default',
659 // Test textarea components.
661 'component' => array(
662 'form_key' => 'textarea',
663 'name' => 'Textarea',
664 'type' => 'textarea',
665 'value' => 'sample textarea default value',
671 'sample values' => 'sample textarea value',
672 'database values' => array('sample textarea value'),
673 'database default values' => array('sample textarea default value'),
674 // Conditionals match against the 'sample values'.
675 'match conditional values' => array(
676 'equal' => 'sample textarea value',
678 'contains' => 'sample',
679 'does_not_contain' => 'foo',
680 'begins_with' => 'sample',
681 'ends_with' => 'value',
684 'mismatch conditional values' => array(
686 'not_equal' => 'sample textarea value',
688 'does_not_contain' => 'sample',
689 'begins_with' => 'value',
690 'ends_with' => 'sample',
695 // Test textfield components.
696 'textfield' => array(
697 'component' => array(
698 'form_key' => 'textfield',
699 'name' => 'Textfield',
700 'type' => 'textfield',
706 'sample values' => '',
707 'database values' => array(''),
708 'database default values' => array(''),
710 'textfield_disabled' => array(
711 'component' => array(
712 'form_key' => 'textfield_disabled',
713 'name' => 'Textfield Disabled',
714 'type' => 'textfield',
715 'value' => '[current-page:query:foo]',
723 // Manually hard-code the input if token is not available.
724 // TODO: Update after http://drupal.org/node/1347790 is finished.
725 'sample values' => module_exists('token') ? NULL : 'bar',
726 'database values' => array('bar'),
727 'database default values' => module_exists('token') ? array('bar') : array(''),
729 'textfield_profile' => array(
730 'component' => array(
731 'form_key' => 'textfield_profile',
732 'name' => 'Textfield Profile',
733 'type' => 'textfield',
734 'value' => '[current-user:gender]',
742 'sample values' => 'Female',
743 'database values' => array('Female'),
744 // The default value will be blank if token does not exist.
745 // TODO: Update after http://drupal.org/node/1347790 is finished.
746 'database default values' => module_exists('token') ? array($this->webform_users['admin']->gender[LANGUAGE_NONE][0]['value']) : array(''),
749 // Test time components.
751 'component' => array(
752 'form_key' => 'time',
755 'value' => '10:30pm',
757 'timezone' => 'site',
758 'hourformat' => '12-hour',
764 'sample values' => array('hour' => '12', 'minute' => '0', 'ampm' => 'pm'),
765 'database values' => array('12:00:00'),
766 'database default values' => array('22:30:00'),
767 // Conditionals match against the 'sample values'.
768 'match conditional values' => array(
769 'equal' => '12:00pm',
770 'before' => '1:00pm',
771 'before_equal' => '12:00pm',
772 'after' => '11:00am',
773 'after_equal' => '11:00am',
775 'mismatch conditional values' => array(
776 'equal' => '12:00am',
777 'before' => '12:00pm',
778 'before_equal' => '11:00am',
779 'after' => '12:00pm',
783 'component' => array(
784 'form_key' => 'time_24h',
785 'name' => 'Time 24H',
787 'value' => '10:30pm',
789 'timezone' => 'site',
790 'hourformat' => '24-hour',
796 'sample values' => array('hour' => '5', 'minute' => '0'),
797 'database values' => array('05:00:00'),
798 'database default values' => array('22:30:00'),
799 // Conditionals match against the 'sample values'.
800 'match conditional values' => array(
803 'before_equal' => '5:00',
805 'after_equal' => '00:00',
807 'mismatch conditional values' => array(
810 'before_equal' => '4:59',
812 'after_equal' => '5:01',
816 // Test number components.
818 'component' => array(
819 'form_key' => 'integer',
824 'type' => 'textfield',
827 // SimpleTest does not support type="number" input fields.
828 'attributes' => array('type' => 'text'),
834 'sample values' => '2',
835 'database values' => array('2'),
836 'database default values' => array('1'),
837 // Conditionals match against the 'sample values'.
838 'match conditional values' => array(
842 'less_than_equal' => '2',
843 'greater_than' => '1',
844 'greater_than_equal' => '1',
847 'mismatch conditional values' => array(
851 'less_than_equal' => '1',
852 'greater_than' => '2',
853 'greater_than_equal' => '3',
856 'error values' => array(
857 '1.5' => t('!name field value of @value must be an integer.', array('!name' => 'Integer', '@value' => '1.5')),
858 '101' => t('!name field value must be less than @max.', array('!name' => 'Integer', '@max' => '100')),
861 'integer_range' => array(
862 'component' => array(
863 'form_key' => 'integer_range',
864 'name' => 'Integer Range',
878 'sample values' => '10',
879 'database values' => array('10'),
880 'database default values' => array('50'),
882 'decimal_positive' => array(
883 'component' => array(
884 'form_key' => 'decimal_positive',
885 'name' => 'Decimal positive',
889 'type' => 'textfield',
890 'field_prefix' => '$',
891 'field_suffix' => 'lbs',
896 // SimpleTest does not support type="number" input fields.
897 'attributes' => array('type' => 'text'),
903 'sample values' => '2.00',
904 'database values' => array('2.00'),
905 'database default values' => array('1'),
906 // Conditionals match against the 'sample values'.
907 'match conditional values' => array(
910 'less_than' => '3.000',
911 'greater_than' => '1.000',
914 'mismatch conditional values' => array(
917 'less_than' => '2.0',
918 'greater_than' => '2.00',
921 'error values' => array(
922 '-1' => t('!name field value must be greater than @min.', array('!name' => 'Decimal positive', '@min' => '0')),
925 'decimal_range' => array(
926 'component' => array(
927 'form_key' => 'decimal_range',
928 'name' => 'Decimal range',
932 'type' => 'textfield',
933 'field_prefix' => '$',
934 'field_suffix' => 'lbs',
938 // SimpleTest does not support type="number" input fields.
939 'attributes' => array('type' => 'text'),
945 'sample values' => '11.5',
946 'database values' => array('11.5'),
947 'database default values' => array('1'),
948 'error values' => array(
949 '2' => t('!name field value must be @start plus a multiple of @step.', array('!name' => 'Decimal range', '@start' => '1', '@step' => '1.5')),
950 '13' => t('!name field value of @value should be in the range @min to @max.', array('!name' => 'Decimal range', '@value' => '13', '@min' => '1', '@max' => '12')),
953 'decimal_range_select' => array(
954 'component' => array(
955 'form_key' => 'decimal_range_select',
956 'name' => 'Decimal range select',
961 'field_prefix' => '$',
962 'field_suffix' => 'lbs',
971 'sample values' => '10',
972 'database values' => array('10'),
973 'database default values' => array('1'),
974 // Conditionals match against the 'sample values'.
975 'match conditional values' => array(
977 'not_equal' => '2.5',
978 'less_than' => '11.5',
979 'greater_than' => '1',
981 'mismatch conditional values' => array(
985 'greater_than' => '11.5',
990 return $this->_webform_components;
993 function testWebformForm() {
994 if (isset($this->_webform_node)) {
995 return $this->_webform_node;
1000 'language' => LANGUAGE_NONE,
1008 'title' => 'Test Webform',
1012 'confirmation' => 'Thanks!',
1013 ) + webform_node_defaults(),
1017 foreach ($this->testWebformComponents() as $key => $component_info) {
1019 $settings['webform']['components'][$cid] = $component_info['component'];
1020 $settings['webform']['components'][$cid]['cid'] = $cid;
1021 $settings['webform']['components'][$cid]['pid'] = 0;
1024 $this->_webform_node = $this->drupalCreateNode($settings);
1026 return $this->_webform_node;
1030 * Generate a list of all values that would result in a valid submission.
1032 * @param $input_values
1033 * An array of input values keyed by the component form key. If none
1034 * are specified, the defaults will be pulled from testWebformComponents().
1036 function testWebformPost($input_values = NULL) {
1039 if (empty($input_values)) {
1040 $input_values = array();
1041 foreach ($this->testWebformComponents() as $key => $component_info) {
1042 $input_values[$key] = $component_info['sample values'];
1046 foreach ($input_values as $key => $values) {
1047 if (is_array($values)) {
1048 foreach ($values as $subkey => $value) {
1049 $edit["submitted[$key][$subkey]"] = $value;
1052 elseif ($values != NULL) {
1054 // Multiple selects have a funky extra empty bracket in the name.
1055 $extra = $key == 'select_multiple' ? '[]' : '';
1056 $edit["submitted[$key]$extra"] = $value;
1063 * Utility function to print out the current page being tested.
1065 function webformPrintPage() {
1066 $this->verbose($this->drupalGetContent());
1071 * Test general functionality of Webform.
1073 class WebformGeneralTestCase extends WebformTestCase {
1075 * Implements getInfo().
1077 public static function getInfo() {
1079 'name' => t('Webform'),
1080 'description' => t('Checks global Webform settings and content types.'),
1081 'group' => t('Webform'),
1086 * Test creating a new Webform node.
1088 function testWebformCreate() {
1090 'title' => 'Test webform, no components',
1091 'type' => 'webform',
1093 $node = $this->drupalCreateNode($settings);
1095 // Because this is a "webform" type node, it should have an entry in the
1096 // database even though it's using the default settings.
1097 $this->assertTrue($this->webformRecordExists($node->nid), t('Webform record made in the database for the new webform node.'));
1099 // Make a change to the node, ensure that the record stays intact.
1100 $node->title .= '!';
1102 $this->assertTrue($this->webformRecordExists($node->nid), t('Webform record still in the database after modifying webform node.'));
1106 * Test webform-enabling a different node type and testing behavior.
1108 function testWebformCreateNewType() {
1109 // Enable webforms on the page content type.
1110 variable_set('webform_node_webform', TRUE);
1111 variable_set('webform_node_page', TRUE);
1114 'title' => 'Test webform-enabled page',
1117 $node = $this->drupalCreateNode($settings);
1119 // Because this is a webform-enabled type node but does not yet have any
1120 // components, it should not have an entry in the database because it is
1121 // using the default settings.
1122 $this->assertFalse($this->webformRecordExists($node->nid), t('Webform record not in the database for the new page node.'));
1124 // Make a change to the node, ensure that the record stays empty.
1125 $node->title .= '!';
1127 $this->assertFalse($this->webformRecordExists($node->nid), t('Webform record still not in the database after modifying page node.'));
1129 // Add a new component to the node and check that a record is made in the
1131 $components = $this->testWebformComponents();
1132 $textarea = $components['textarea'];
1133 $textarea['type'] = 'textarea';
1134 $textarea['form_key'] = 'textarea';
1135 $textarea['cid'] = 1;
1136 $textarea['pid'] = 0;
1137 $textarea = array_merge(webform_component_invoke('textarea', 'defaults'), $textarea);
1138 $node->webform['components'][1] = $textarea;
1140 $this->assertTrue($this->webformRecordExists($node->nid), t('Webform record now exists after adding a new component.'));
1142 // Remove the new component and ensure that the record is deleted.
1143 $node->webform['components'] = array();
1145 $this->assertFalse($this->webformRecordExists($node->nid), t('Webform record deleted after deleting last component.'));
1148 function webformRecordExists($nid) {
1149 return (bool) db_query("SELECT nid FROM {webform} WHERE nid = :nid", array(':nid' => $nid))->fetchField();