5 * Webform CiviCRM module's admin form.
8 class wf_crm_admin_form {
17 function __construct($form, &$form_state, $node) {
18 module_load_include('inc', 'webform_civicrm', 'includes/utils');
19 module_load_include('inc', 'webform_civicrm', 'includes/wf_crm_admin_help');
22 $this->form_state = &$form_state;
24 $this->fields = wf_crm_get_fields();
25 $this->sets = wf_crm_get_fields('sets');
29 * Build admin form for civicrm tab of a webform
32 public function buildForm() {
33 $this->form_state['storage']['nid'] = $this->node->nid;
35 // Display confirmation message before deleting fields
36 if (!empty($this->form_state['storage']['msg'])) {
37 return $this->buildConfirmationForm();
41 $this->addResources();
43 if (empty($this->form_state['values'])) {
44 $this->initializeForm();
49 // Merge in existing fields
50 $existing = array_keys(wf_crm_enabled_fields($this->node, NULL, TRUE));
51 $this->settings += array_fill_keys($existing, 'create_civicrm_webform_element');
54 foreach ($this->fields as $fid => $field) {
55 if (isset($field['set'])) {
59 list($set) = explode('_', $fid, 2);
61 $this->sets[$set]['fields'][$fid] = $field;
65 $this->buildFormIntro();
66 foreach ($this->data['contact'] as $n => $c) {
67 $this->buildContactTab($n, $c);
69 $this->buildMessageTabs();
72 $this->buildActivityTab();
73 if (isset($this->sets['case'])) {
74 $this->buildCaseTab();
76 if (isset($this->sets['participant'])) {
77 $this->buildParticipantTab();
79 if (isset($this->sets['membership'])) {
80 $this->buildMembershipTab();
82 if (isset($this->sets['contribution'])) {
83 $this->buildContributionTab();
85 if (isset($this->sets['grant'])) {
86 $this->buildGrantTab();
88 $this->buildOptionsTab();
90 $this->form['actions']['submit'] = array(
92 '#value' => t('Save Settings'),
98 * Initialize form on first view
100 private function initializeForm() {
101 $this->settings = isset($this->node->webform_civicrm) ? $this->node->webform_civicrm : $this->defaultSettings();
102 $this->data = &$this->settings['data'];
103 // Warn of incompatible modules
104 $incompatibilities = array(
105 'form_builder_webform' => t('Form builder Webform UI'),
106 'webform_alt_ui' => t('Webform Alternate UI'),
108 foreach ($incompatibilities as $module => $label) {
109 if (module_exists($module)) {
110 drupal_set_message(t('The module %module is not compatible with Webform CiviCRM Integration. Please disable it before continuing.', array('%module' => $label)), 'error');
116 * On rebuilding the form
118 private function rebuildForm() {
119 $this->settings = wf_crm_aval($this->form_state['storage'], 'vals', $this->form_state['values']);
120 $this->rebuildData();
121 // Hack for nicer UX: pre-check phone, email, etc when user increments them
122 if (!empty($_POST['_triggering_element_name'])) {
123 foreach (array('phone' => 'phone', 'email' => 'email', 'website' => 'url', 'im' => 'name') as $ent => $field) {
124 if (strpos($_POST['_triggering_element_name'], "_number_of_$ent")) {
125 list(, $c) = explode('_', $_POST['_triggering_element_name']);
126 for ($n = 1; $n <= $this->data['contact'][$c]["number_of_$ent"]; ++$n) {
127 $this->settings["civicrm_{$c}_contact_{$n}_{$ent}_{$field}"] = 1;
132 unset($this->form_state['storage']['vals']);
136 * Display confirmation message and buttons before deleting webform components
139 private function buildConfirmationForm() {
140 $this->form['#prefix'] = $this->form_state['storage']['msg'];
141 $this->form['cancel'] = $this->form['disable'] = $this->form['delete'] = array('#type' => 'submit');
142 $this->form['delete']['#value'] = t('Remove Fields and Save Settings');
143 $this->form['disable']['#value'] = t('Leave Fields and Save Settings');
144 $this->form['cancel']['#value'] = t('Cancel (go back)');
149 * Add necessary css & js
151 private function addResources() {
152 $this->form['#attached']['css'][] = drupal_get_path('module', 'webform_civicrm') . '/css/webform_civicrm_admin.css';
153 $this->form['#attached']['js'][] = drupal_get_path('module', 'webform_civicrm') . '/js/webform_civicrm_admin.js';
154 $this->form['#attached']['js'][] = array(
155 'data' => array('webform_civicrm' => array('rTypes' => wf_crm_get_relationship_types())),
158 // Add CiviCRM core css & js, which includes jQuery, jQuery UI + other plugins
159 CRM_Core_Resources::singleton()->addCoreResources();
160 // Markup needed by CRM popup notifications
161 $this->form['#suffix'] = wf_crm_admin_help::helpTemplate();
165 * Build fields for form intro
167 private function buildFormIntro() {
168 $this->form['nid'] = array(
169 '#type' => 'checkbox',
170 '#title' => t('Enable CiviCRM Processing'),
171 '#default_value' => !empty($this->settings['nid']),
172 '#return_value' => $this->node->nid,
174 $this->help($this->form['nid'], 'intro', t('Webform-CiviCRM Integration'));
175 $this->form['number_of_contacts'] = array(
177 '#title' => t('Number of Contacts'),
178 '#default_value' => count($this->data['contact']),
179 '#options' => drupal_map_assoc(range(1, 30)),
181 $this->form['change_form_settings'] = array(
183 '#value' => t('Change Form Settings'),
184 '#prefix' => '<div id="no-js-button-wrapper" class="messages warning">',
185 '#suffix' => '<div>' . t('You have Javascript disabled. You will need to click this button after changing any option to see the result.') . '</div></div>',
187 $this->form['webform_civicrm'] = array('#type' => 'vertical_tabs');
188 // Display intro help to virgins
189 if (!variable_get('webform_civicrm_help_seen')) {
190 variable_set('webform_civicrm_help_seen', TRUE);
191 drupal_add_js('cj(function() {CRM.help("' . t('Welcome to Webform-CiviCRM') . '", {}, "' . url('webform-civicrm/help/intro') . '");});', array('type' => 'inline', 'scope' => 'footer'));
196 * Build fields for a contact
197 * @param int $n Contact number
198 * @param array $c Contact info
200 private function buildContactTab($n, $c) {
201 list($contact_types, $sub_types) = wf_crm_get_contact_types();
202 $this->form['contact_' . $n] = array(
203 '#type' => 'fieldset',
204 '#title' => $n . '. ' . wf_crm_contact_label($n, $this->data),
205 '#description' => $n > 1 ? NULL : t('Primary contact. Usually assumed to be the person filling out the form.') . '<br />' . t('Enable the "Existing Contact" field to autofill with the current user (or another contact).'),
206 '#group' => 'webform_civicrm',
207 '#attributes' => array('class' => array('contact-icon-' . $c['contact'][1]['contact_type'])),
209 $this->form['contact_' . $n][$n . '_contact_type'] = array(
211 '#title' => t('Contact Type'),
212 '#default_value' => $c['contact'][1]['contact_type'],
213 '#options' => $contact_types,
214 '#prefix' => '<div class="contact-type-select">',
216 $this->form['contact_' . $n][$n . '_webform_label'] = array(
217 '#type' => 'textfield',
218 '#title' => t('Label'),
219 '#default_value' => wf_crm_contact_label($n, $this->data, 'plain'),
220 '#suffix' => '</div>',
222 $this->help($this->form['contact_' . $n][$n . '_webform_label'], 'webform_label', t('Contact Label'));
223 $this->addAjaxItem('contact_' . $n, $n . '_contact_type', 'contact_subtype_wrapper', 'contact-subtype-wrapper');
226 $fid = 'civicrm_' . $n . '_contact_1_contact_contact_sub_type';
227 $subTypeIsUserSelect = FALSE;
228 if (!empty($sub_types[$c['contact'][1]['contact_type']])) {
229 $field = $this->fields['contact_contact_sub_type'];
230 $field['name'] = t('Type of @contact', array('@contact' => $contact_types[$c['contact'][1]['contact_type']]));
231 $this->form['contact_' . $n]['contact_subtype_wrapper'][$fid] = $subTypeField = $this->addItem($fid, $field);
232 $subTypeIsUserSelect = in_array('create_civicrm_webform_element', $subTypeField['#default_value']);
233 $this->addAjaxItem('contact_' . $n . ':contact_subtype_wrapper', $fid, 'contact_custom_wrapper');
237 $this->form['contact_' . $n]['contact_subtype_wrapper'][$fid] = array(
243 $this->form['contact_' . $n]['contact_subtype_wrapper']['clear'] = array(
244 '#markup' => '<div class="clearfix"> </div>',
247 foreach ($this->sets as $sid => $set) {
248 if ($set['entity_type'] != 'contact') {
251 if ($sid == 'relationship' && !($set['max_instances'] = $n - 1)) {
254 if (!empty($set['contact_type']) && $set['contact_type'] != $c['contact'][1]['contact_type']) {
257 if (!empty($set['sub_types'])) {
258 if (!$subTypeIsUserSelect && !array_intersect($c['contact'][1]['contact_sub_type'], $set['sub_types'])) {
261 $pos = &$this->form['contact_' . $n]['contact_subtype_wrapper']['contact_custom_wrapper'];
262 $path = 'contact_' . $n . ':contact_subtype_wrapper:contact_custom_wrapper';
264 elseif (!empty($set['contact_type']) || $sid == 'contact') {
265 $pos = &$this->form['contact_' . $n]['contact_subtype_wrapper'];
266 $path = 'contact_' . $n . ':contact_subtype_wrapper';
269 $pos = &$this->form['contact_' . $n];
270 $path = 'contact_' . $n;
272 if (!empty($set['max_instances'])) {
273 if (!isset($c['number_of_' . $sid])) {
274 $c['number_of_' . $sid] = 0;
278 '#default_value' => $c['number_of_' . $sid],
279 '#prefix' => '<div class="number-of">',
280 '#suffix' => '</div>',
282 if ($set['max_instances'] > 1) {
283 $selector['#options'] = range(0, $set['max_instances']);
284 $selector['#title'] = t('Number of %type Fields', array('%type' => $set['label']));
287 $selector['#options'] = array(t('No'), t('Yes'));
288 $selector['#title'] = t('Enable %type Fields', array('%type' => $set['label']));
290 if (!empty($set['help_text'])) {
291 $this->help($selector, "fieldset_$sid", $set['label']);
293 $pos['contact_' . $n . '_number_of_' . $sid] = $selector;
294 $this->addAjaxItem($path, 'contact_' . $n . '_number_of_' . $sid, $n . $sid . '_wrapper');
297 $c['number_of_' . $sid] = 1;
299 for ($i = 1; $i <= $c['number_of_' . $sid]; ++$i) {
300 $fsid = 'civicrm_' . $n . $sid . $i . '_fieldset';
302 '#type' => 'fieldset',
303 '#title' => $set['label'],
304 '#attributes' => array('id' => $fsid, 'class' => array('web-civi-checkbox-set')),
305 'js_select' => $this->addToggle($fsid),
307 if ($sid == 'relationship') {
308 $fieldset['#title'] = t('Relationship to !contact', array('!contact' => wf_crm_contact_label($i, $this->data, 'wrap')));
310 elseif ((isset($set['max_instances']) && $set['max_instances'] > 1)) {
311 $fieldset['#title'] .= ' ' . $i;
312 if (in_array($sid, wf_crm_location_fields()) && $i == 1) {
313 $fieldset['#title'] .= ' ' . t('(primary)');
316 foreach ($set['fields'] as $fid => $field) {
317 if ($fid == 'contact_contact_sub_type' ||
318 ($fid == 'address_master_id' && count($this->data['contact']) == 1) ||
319 (isset($field['contact_type']) && $field['contact_type'] != $c['contact'][1]['contact_type'])) {
322 $fid = 'civicrm_' . $n . '_contact_' . $i . '_' . $fid;
323 $fieldset[$fid] = $this->addItem($fid, $field);
325 if (isset($set['max_instances'])) {
326 $pos[$n . $sid . '_wrapper'][$n . $sid . $i . '_fieldset'] = $fieldset;
329 $pos[$n . $sid . $i . '_fieldset'] = $fieldset;
332 if ($sid == 'contact') {
334 $rule_field = $this->form['contact_' . $n]['contact_subtype_wrapper']["contact_{$n}_settings_matching_rule"] = array(
338 'Unsupervised' => t('Default Unsupervised'),
339 'Supervised' => t('Default Supervised'),
340 ) + wf_crm_get_matching_rules($c['contact'][1]['contact_type']),
341 '#title' => t('Matching Rule'),
342 '#prefix' => '<div class="number-of">',
343 '#suffix' => '</div>',
344 '#default_value' => wf_crm_aval($this->data['contact'][$n], 'matching_rule', 'Unsupervised', TRUE),
346 $rule_field =& $this->form['contact_' . $n]['contact_subtype_wrapper']["contact_{$n}_settings_matching_rule"];
347 // Reset to default if selected rule doesn't exist or isn't valid for this contact type
348 if (!array_key_exists($rule_field['#default_value'], $rule_field['#options'])) {
349 $rule_field['#default_value'] = $this->form_state['input']["contact_{$n}_settings_matching_rule"] = 'Unsupervised';
351 $this->help($rule_field, 'matching_rule');
359 private function buildMessageTabs() {
360 $tokens = '<strong>' . t('Tokens for !contact', array('!contact' => wf_crm_contact_label(1, $this->data, TRUE))) . ':</strong> [' . implode('], [', wf_crm_get_fields('tokens')) . '].';
362 $this->form['prefix'] = array(
363 '#type' => 'fieldset',
364 '#title' => t('Introduction Text'),
365 '#description' => t('This text will appear at the top of the form. You may configure separate messages for known contacts (logged in users, or users following a hashed link from civimail) and unknown (anonymous) users.'),
366 '#group' => 'webform_civicrm',
367 '#attributes' => array('class' => array('civi-icon-text')),
369 $this->form['prefix']['prefix_known'] = array(
370 '#type' => 'textarea',
371 '#title' => t('Introduction text for known contacts'),
372 '#default_value' => wf_crm_aval($this->settings, 'prefix_known'),
373 '#description' => $tokens,
375 $this->form['prefix']['prefix_unknown'] = array(
376 '#type' => 'textarea',
377 '#title' => t('Introduction text for unknown contacts'),
378 '#default_value' => wf_crm_aval($this->settings, 'prefix_unknown'),
379 '#description' => t('No tokens available for unknown contacts.'),
381 $this->form['st_message'] = array(
382 '#type' => 'fieldset',
383 '#title' => t('"Not You?" Message'),
384 '#description' => t('Prompt for users who are logged in as, or following a hashed link for, someone else.'),
385 '#group' => 'webform_civicrm',
386 '#attributes' => array('class' => array('civi-icon-message')),
388 $this->form['st_message']['toggle_message'] = array(
389 '#type' => 'checkbox',
390 '#title' => t('Display message to known contacts?'),
391 '#default_value' => !empty($this->settings['message']),
393 $this->form['st_message']['message'] = array(
394 '#type' => 'textfield',
395 '#title' => t('Text (displayed as a status message)'),
396 '#default_value' => wf_crm_aval($this->settings, 'message', t("You are viewing this form as [display name]. Please {click here if that's not you}.")),
399 '#attributes' => array('style' => 'max-width: 100%;'),
400 '#description' => t('Enclose your "not you" link text in curly brackets {like this}.') . '<p>' . $tokens . '</p>',
407 private function buildActivityTab() {
408 $this->form['activityTab'] = array(
409 '#type' => 'fieldset',
410 '#title' => t('Activities'),
411 '#group' => 'webform_civicrm',
412 '#attributes' => array('class' => array('civi-icon-activity')),
414 $num_acts = wf_crm_aval($this->data, "activity:number_of_activity", 0);
415 $this->form['activityTab']["activity_number_of_activity"] = array(
417 '#title' => t('Number of Activities'),
418 '#default_value' => $num_acts,
419 '#options' => range(0, $this->sets['activity']['max_instances']),
420 '#prefix' => '<div class="number-of">',
421 '#suffix' => '</div>',
423 $this->addAjaxItem("activityTab", "activity_number_of_activity", "activity");
424 for ($n = 1; $n <= $num_acts; ++$n) {
425 $num = "activity_activity_{$n}_fieldset";
426 $this->form['activityTab']['activity'][$num] = array(
427 '#type' => 'fieldset',
428 '#attributes' => array('class' => array('activity-wrapper')),
429 '#title' => t('Activity !num', array('!num' => $n)),
431 $this->form['activityTab']['activity'][$num]["activity_{$n}_settings_existing_activity_status"] = array(
433 '#title' => t('Update Existing Activity'),
434 '#options' => array('' => '- ' . t('None') . ' -') + wf_crm_apivalues('activity', 'getoptions', array('field' => 'status_id')),
435 '#default_value' => wf_crm_aval($this->data, "activity:$n:existing_activity_status", array()),
437 '#prefix' => '<div class="float-item">',
438 '#suffix' => '</div>',
440 $this->help($this->form['activityTab']['activity'][$num]["activity_{$n}_settings_existing_activity_status"], 'existing_activity_status');
441 $this->form['activityTab']['activity'][$num]["activity_{$n}_settings_details"] = array(
442 '#type' => 'checkboxes',
444 'entire_result' => t('Include <em>entire</em> webform submission in activity details'),
445 'view_link' => t('Include link to <em>view</em> webform submission in activity details'),
446 'edit_link' => t('Include link to <em>edit</em> webform submission in activity details'),
448 '#default_value' => wf_crm_aval($this->data, "activity:$n:details", array('view_link'), TRUE),
450 $this->form['activityTab']['activity'][$num]['wrap'] = array();
451 $wrap = &$this->form['activityTab']['activity'][$num]['wrap'];
452 if (isset($this->sets['case'])) {
453 $case_types = wf_crm_apivalues('case', 'getoptions', array('field' => 'case_type_id'));
455 $wrap['case']["activity_{$n}_settings_case_type_id"] = array(
457 '#title' => t('File On Case'),
458 '#options' => array(t('- None -')) + $case_types,
459 '#default_value' => $case_type = wf_crm_aval($this->data, "activity:$n:case_type_id"),
461 // Allow selection of webform cases
462 $num_case = wf_crm_aval($this->data, "case:number_of_case", 0);
464 $webform_cases = array();
465 for ($i=1; $i<=$num_case; ++$i) {
466 $webform_cases["#$i"] = t('Case !num', array('!num' => $i));
468 $wrap['case']["activity_{$n}_settings_case_type_id"]['#options'] = array(
470 t('This Webform') => $webform_cases,
471 t('Find by Case Type') => $case_types,
474 $this->help($wrap['case']["activity_{$n}_settings_case_type_id"], 'file_on_case');
475 $this->addAjaxItem("activityTab:activity:$num:wrap:case", "activity_{$n}_settings_case_type_id", '..:..:wrap');
476 if ($case_type && $case_type[0] !== '#') {
477 $wrap['case']['#type'] = 'fieldset';
478 $wrap['case']['#attributes'] = array('class' => array('web-civi-checkbox-set'));
479 $wrap['case']['#title'] = t('File On Case');
480 $wrap['case']['#description'] = t('File on existing case matching the following criteria:');
481 $this->help($wrap['case'], 'file_on_case');
482 $wrap['case']["activity_{$n}_settings_case_type_id"]['#title'] = t('Case Type');
483 $status_options = wf_crm_apivalues('case', 'getoptions', array('field' => 'status_id'));
484 $wrap['case']["activity_{$n}_settings_case_status_id"] = array(
486 '#title' => t('Case Status'),
487 '#options' => $status_options,
489 '#attributes' => array('class' => array('required')),
490 '#default_value' => wf_crm_aval($this->data, "activity:$n:case_status_id", array_keys($status_options)),
492 $wrap['case']["activity_{$n}_settings_case_contact_id"] = array(
494 '#title' => t('Case Client'),
495 '#attributes' => array('data-type' => 'ContactReference'),
496 '#options' => $this->contactRefOptions(),
497 '#default_value' => wf_crm_aval($this->data, "activity:$n:case_contact_id"),
502 $wrap[$num . '_fields'] = array(
503 '#type' => 'fieldset',
504 '#title' => ts('Activity'),
505 '#attributes' => array('id' => $num . '_fields', 'class' => array('web-civi-checkbox-set')),
506 'js_select' => $this->addToggle($num . '_fields'),
508 foreach ($this->sets['activity']['fields'] as $fid => $field) {
509 if ($fid != 'activity_survey_id') {
510 $fid = "civicrm_{$n}_activity_1_$fid";
511 $wrap[$num . '_fields'][$fid] = $this->addItem($fid, $field);
514 $type = $wrap[$num . '_fields']["civicrm_{$n}_activity_1_activity_activity_type_id"]['#default_value'];
515 $type = $type == 'create_civicrm_webform_element' ? 0 : $type;
516 $this->addAjaxItem("activityTab:activity:$num:wrap:{$num}_fields", "civicrm_{$n}_activity_1_activity_activity_type_id", "..:custom");
517 // Add ajax survey type field
518 if (isset($this->fields['activity_survey_id'])) {
519 $this->addAjaxItem("activityTab:activity:$num:wrap:{$num}_fields", "civicrm_{$n}_activity_1_activity_campaign_id", "..:custom");
520 if ($type && array_key_exists($type, wf_crm_get_campaign_activity_types())) {
521 $this->sets['activity_survey'] = array(
522 'entity_type' => 'activity',
523 'label' => $wrap[$num . '_fields']["civicrm_{$n}_activity_1_activity_activity_type_id"]['#options'][$type],
525 'activity_survey_id' => $this->fields['activity_survey_id'],
530 // Add custom field sets appropriate to this activity type
531 foreach ($this->sets as $sid => $set) {
532 if ($set['entity_type'] == 'activity' && $sid != 'activity'
533 && (!$type || empty($set['sub_types']) || in_array($type, $set['sub_types']))
535 $fs1 = "activity_activity_{$n}_fieldset_$sid";
536 $wrap['custom'][$fs1] = array(
537 '#type' => 'fieldset',
538 '#title' => $set['label'],
539 '#attributes' => array('id' => $fs1, 'class' => array('web-civi-checkbox-set')),
540 'js_select' => $this->addToggle($fs1),
542 foreach ($set['fields'] as $fid => $field) {
543 $fid = "civicrm_{$n}_activity_1_$fid";
544 $wrap['custom'][$fs1][$fid] = $this->addItem($fid, $field);
553 * FIXME: This is exactly the same code as buildGrantTab. More utilities and less boilerplate needed.
555 private function buildCaseTab() {
556 $types = wf_crm_apivalues('case', 'getoptions', array('field' => 'case_type_id'));
560 $this->form['caseTab'] = array(
561 '#type' => 'fieldset',
562 '#title' => t('Cases'),
563 '#group' => 'webform_civicrm',
564 '#attributes' => array('class' => array('civi-icon-case')),
566 $this->form['caseTab']["case_number_of_case"] = array(
568 '#title' => t('Number of Cases'),
569 '#default_value' => $num = wf_crm_aval($this->data, "case:number_of_case", 0),
570 '#options' => range(0, $this->sets['case']['max_instances']),
571 '#prefix' => '<div class="number-of">',
572 '#suffix' => '</div>',
574 $this->addAjaxItem("caseTab", "case_number_of_case", "case");
575 for ($n = 1; $n <= $num; ++$n) {
576 $fs = "case_case_{$n}_fieldset";
577 $this->form['caseTab']['case'][$fs] = array(
578 '#type' => 'fieldset',
579 '#title' => t('Case !num', array('!num' => $n)),
580 'wrap' => array('#weight' => 9),
582 $this->form['caseTab']['case'][$fs]["case_{$n}_settings_existing_case_status"] = array(
584 '#title' => t('Update Existing Case'),
585 '#options' => array('' => '- ' . t('None') . ' -') + wf_crm_apivalues('case', 'getoptions', array('field' => 'status_id')),
586 '#default_value' => wf_crm_aval($this->data, "case:{$n}:existing_case_status", array()),
589 $this->help($this->form['caseTab']['case'][$fs]["case_{$n}_settings_existing_case_status"], 'existing_case_status');
590 $case_type = wf_crm_aval($this->data, "case:{$n}:case:1:case_type_id");
591 foreach ($this->filterCaseSets($case_type) as $sid => $set) {
592 $fs1 = "case_case_{$n}_fieldset_$sid";
593 if ($sid == 'case') {
594 $pos = &$this->form['caseTab']['case'][$fs];
597 $pos = &$this->form['caseTab']['case'][$fs]['wrap'];
600 '#type' => 'fieldset',
601 '#title' => $set['label'],
602 '#attributes' => array('id' => $fs1, 'class' => array('web-civi-checkbox-set')),
603 'js_select' => $this->addToggle($fs1),
605 foreach ($set['fields'] as $fid => $field) {
606 $fid = "civicrm_{$n}_case_1_$fid";
607 if (!$case_type || empty($field['case_types']) || in_array($case_type, $field['case_types'])) {
608 $pos[$fs1][$fid] = $this->addItem($fid, $field);
612 $this->addAjaxItem("caseTab:case:$fs:case_case_{$n}_fieldset_case", "civicrm_{$n}_case_1_case_case_type_id", "..:wrap");
617 * Adjust case role fields to match creator/manager settings for a given case type
619 * @param int|null $case_type
622 private function filterCaseSets($case_type) {
623 $case_sets = array();
624 foreach ($this->sets as $sid => $set) {
625 if ($set['entity_type'] == 'case' && (!$case_type || empty($set['sub_types']) || in_array($case_type, $set['sub_types']))) {
626 if ($sid == 'caseRoles') {
627 // Lookup case-role names
628 $creator = $manager = NULL;
629 // Use the vanilla civicrm_api for this because it will throw an error in CiviCRM 4.4 (api doesn't exist)
630 $case_types = civicrm_api('case_type', 'get', array('version' => 3, 'id' => $case_type, 'options' => array('limit' => 0)));
631 foreach (wf_crm_aval($case_types, 'values', array()) as $type) {
632 foreach ($type['definition']['caseRoles'] as $role) {
633 if (!empty($role['creator'])) {
634 $creator = ($creator == $role['name'] || $creator === NULL) ? $role['name'] : FALSE;
636 if (!empty($role['manager'])) {
637 $manager = ($manager == $role['name'] || $manager === NULL) ? $role['name'] : FALSE;
642 $rel_type = wf_civicrm_api('relationshipType', 'getsingle', array('name_b_a' => $creator));
643 $label = $creator == $manager ? ts('Case # Creator/Manager') : ts('Case # Creator');
644 $set['fields']['case_creator_id']['name'] = $rel_type['label_b_a'] . ' (' . $label . ')';
645 unset($set['fields']['case_role_' . $rel_type['id']]);
647 if ($manager && $manager != $creator) {
648 $rel_type = wf_civicrm_api('relationshipType', 'getsingle', array('name_b_a' => $manager));
649 $set['fields']['case_role_' . $rel_type['id']]['name'] .= ' (' . ts('Case # Manager') . ')';
652 $case_sets[$sid] = $set;
659 * Event participant settings
661 private function buildParticipantTab() {
662 $this->form['participant'] = array(
663 '#type' => 'fieldset',
664 '#title' => t('Event Registration'),
665 '#group' => 'webform_civicrm',
666 '#attributes' => array('class' => array('civi-icon-participant')),
668 $reg_type = wf_crm_aval($this->data, 'participant_reg_type');
669 $this->form['participant']['participant_reg_type'] = array(
671 '#title' => t('Registration Method'),
672 '#default_value' => $reg_type,
675 'all' => t('Register all contacts for the same event(s)'),
676 'separate' => t('Register each contact separately'),
679 $this->help($this->form['participant']['participant_reg_type'], 'participant_reg_type');
680 $this->form['participant']['event_type'] = array(
682 '#title' => t('Show Events of Type'),
683 '#options' => array('any' => t('- Any Type -')) + wf_crm_apivalues('event', 'getoptions', array('field' => 'event_type_id')),
684 '#default_value' => wf_crm_aval($this->data, 'reg_options:event_type', 'any'),
685 '#prefix' => '<div id="event-reg-options-wrapper"><div class="web-civi-checkbox-set">',
686 '#parents' => array('reg_options', 'event_type'),
689 $this->form['participant']['show_past_events'] = array(
691 '#title' => t('Show Past Events'),
692 '#default_value' => wf_crm_aval($this->data, 'reg_options:show_past_events', 'now'),
693 '#parents' => array('reg_options', 'show_past_events'),
696 'now' => t('- None -'),
698 '-1 day' => t('Past Day'),
699 '-1 week' => t('Past Week'),
700 '-1 month' => t('Past Month'),
701 '-2 month' => t('Past 2 Months'),
702 '-3 month' => t('Past 3 Months'),
703 '-6 month' => t('Past 6 Months'),
704 '-1 year' => t('Past Year'),
705 '-2 year' => t('Past 2 Years'),
708 $this->help($this->form['participant']['show_past_events'], 'reg_options_show_past_events');
709 $this->form['participant']['show_future_events'] = array(
711 '#title' => t('Show Future Events'),
712 '#default_value' => wf_crm_aval($this->data, 'reg_options:show_future_events', 1),
713 '#parents' => array('reg_options', 'show_future_events'),
716 'now' => t('- None -'),
718 '+1 day' => t('Next Day'),
719 '+1 week' => t('Next Week'),
720 '+1 month' => t('Next Month'),
721 '+2 month' => t('Next 2 Months'),
722 '+3 month' => t('Next 3 Months'),
723 '+6 month' => t('Next 6 Months'),
724 '+1 year' => t('Next Year'),
725 '+2 year' => t('Next 2 Years'),
728 $this->help($this->form['participant']['show_future_events'], 'reg_options_show_future_events');
729 $this->form['participant']['title_display'] = array(
731 '#title' => t('Title Display'),
732 '#default_value' => wf_crm_aval($this->data, 'reg_options:title_display', 'title'),
733 '#suffix' => '</div>',
734 '#parents' => array('reg_options', 'title_display'),
737 'title' => t('Title Only'),
738 'title type' => t('Title + Event Type'),
739 'title start dateformatYear' => t('Title + Year'),
740 'title start dateformatPartial' => t('Title + Month + Year'),
741 'title start dateformatFull' => t('Title + Start-Date'),
742 'title start dateformatTime' => t('Title + Start-Time'),
743 'title start dateformatDatetime' => t('Title + Start-Date-Time'),
744 'title start end dateformatFull' => t('Title + Start-Date + End'),
745 'title start end dateformatTime' => t('Title + Start-Time + End'),
746 'title start end dateformatDatetime' => t('Title + Start-Date-Time + End'),
749 $this->help($this->form['participant']['title_display'], 'reg_options_title_display');
750 $this->form['participant']['reg_options'] = array(
751 '#prefix' => '<div class="clearfix"> </div>',
752 '#suffix' => '</div>',
753 '#type' => 'fieldset',
754 '#title' => t('Registration Options'),
755 '#collapsible' => TRUE,
756 '#collapsed' => isset($this->data['participant']),
761 '#title' => t('Show Remaining Space in Events'),
762 '#default_value' => wf_crm_aval($this->data, 'reg_options:show_remaining', 0),
765 'always' => t('Always'),
766 '0_full' => t('When full - 0 spaces left'),
769 $this->help($field, 'reg_options_show_remaining');
770 foreach (array(5, 10, 20, 50, 100, 200, 500, 1000) as $num) {
771 $field['#options'][$num]['wrap'] = t('When under !num spaces left', array('!num' => $num));
773 $this->form['participant']['reg_options']['show_remaining'] = $field;
774 $this->form['participant']['reg_options']['validate'] = array(
775 '#type' => 'checkbox',
776 '#title' => t('Prevent Registration for Past/Full Events'),
777 '#default_value' => (bool) wf_crm_aval($this->data, 'reg_options:validate'),
779 $this->help($this->form['participant']['reg_options']['validate'], 'reg_options_validate');
780 $this->form['participant']['reg_options']['block_form'] = array(
781 '#type' => 'checkbox',
782 '#title' => t('Block Form Access when Event(s) are Full/Ended'),
783 '#default_value' => (bool) wf_crm_aval($this->data, 'reg_options:block_form'),
785 $this->form['participant']['reg_options']['disable_unregister'] = array(
786 '#type' => 'checkbox',
787 '#title' => t('Disable unregistering participants from unselected events.'),
788 '#default_value' => (bool) wf_crm_aval($this->data, 'reg_options:disable_unregister'),
790 $this->form['participant']['reg_options']['allow_url_load'] = array(
791 '#type' => 'checkbox',
792 '#title' => t('Allow events to be autoloaded from URL'),
793 '#default_value' => (bool) wf_crm_aval($this->data, 'reg_options:allow_url_load'),
795 $this->help($this->form['participant']['reg_options']['block_form'], 'reg_options_block_form');
796 $this->help($this->form['participant']['reg_options']['disable_unregister'], 'reg_options_disable_unregister');
797 $this->help($this->form['participant']['reg_options']['allow_url_load'], 'reg_options_allow_url_load');
798 $this->addAjaxItem('participant', 'participant_reg_type', 'participants');
799 $this->addAjaxItem('participant', 'event_type', 'participants');
800 $this->addAjaxItem('participant', 'show_past_events', 'participants');
801 $this->addAjaxItem('participant', 'show_future_events', 'participants');
802 $this->addAjaxItem('participant', 'title_display', 'participants');
804 for ($n = 1; $reg_type && (($n <= count($this->data['contact']) && $reg_type != 'all') || $n == 1); ++$n) {
805 $this->form['participant']['participants'][$n] = array(
806 '#type' => 'fieldset',
807 '#title' => $reg_type == 'all' ? t('Registration') : wf_crm_contact_label($n, $this->data, 'wrap'),
809 $num = wf_crm_aval($this->data, "participant:{$n}:number_of_participant");
810 if (!$num || ($n > 1 && $reg_type == 'all')) {
813 $this->form['participant']['participants'][$n]['participant_' . $n . '_number_of_participant'] = array(
815 '#title' => $reg_type == 'all' ? t('Number of Event Sets') : t('Number of Event Sets for !contact', array('!contact' => wf_crm_contact_label($n, $this->data, 'wrap'))),
816 '#default_value' => $num,
817 '#options' => range(0, $this->sets['participant']['max_instances']),
818 '#prefix' => '<div class="number-of">',
819 '#suffix' => '</div>',
821 $this->addAjaxItem("participant:participants:{$n}", 'participant_' . $n . '_number_of_participant', 'div');
822 $particpant_extensions = array(
827 for ($e = 1; $e <= $num; ++$e) {
828 $fs = "participant_{$n}_event_{$e}_fieldset";
829 $this->form['participant']['participants'][$n]['div'][$fs] = array(
830 '#type' => 'fieldset',
831 '#title' => t('Event !num', array('!num' => $e)),
832 '#attributes' => array('id' => $fs),
834 foreach ($this->sets as $sid => $set) {
835 if ($set['entity_type'] == 'participant') {
836 $sid = 'civicrm_' . $n . '_participant_' . $e . '_' . $sid . '_fieldset';
837 $class = 'web-civi-checkbox-set';
838 if (!empty($set['sub_types'])) {
839 $role_id = wf_crm_aval($this->data, "participant:$n:particpant:$e:role_id", '');
840 $event_id = wf_crm_aval($this->data, "participant:$n:particpant:$e:event_id", '');
841 $event_type = wf_crm_aval($this->data, 'reg_options:event_type', '');
842 if ($event_id && $event_id !== 'create_civicrm_webform_element') {
843 list($event_id, $event_type) = explode('-', $event_id);
845 $ext = $particpant_extensions[$set['extension_of']];
846 if (!in_array($$ext, $set['sub_types'])) {
849 $class .= ' extends-condition ' . str_replace('_', '', $ext) . '-' . implode('-', $set['sub_types']);
851 $this->form['participant']['participants'][$n]['div'][$fs][$sid] = array(
852 '#type' => 'fieldset',
853 '#title' => $set['label'],
854 '#attributes' => array('id' => $sid, 'class' => array($class)),
855 'js_select' => $this->addToggle($sid),
857 foreach ($set['fields'] as $fid => $field) {
858 $id = 'civicrm_' . $n . '_participant_' . $e . '_' . $fid;
859 $item = $this->addItem($id, $field);
860 if ($fid == 'participant_event_id') {
861 $item['#prefix'] = '<div class="auto-width">';
862 $item['#suffix'] = '</div>';
864 if ($fid == 'participant_event_id' || $fid == 'participant_role_id') {
865 $item['#attributes']['onchange'] = "wfCiviAdmin.participantConditional('#$fs');";
866 $item['#attributes']['class'][] = $fid;
867 $$fid = wf_crm_aval($item, '#default_value');
869 $this->form['participant']['participants'][$n]['div'][$fs][$sid][$id] = $item;
878 * Membership settings
880 private function buildMembershipTab() {
881 $this->form['membership'] = array(
882 '#type' => 'fieldset',
883 '#title' => t('Memberships'),
884 '#group' => 'webform_civicrm',
885 '#attributes' => array('class' => array('civi-icon-membership')),
887 for ($c = 1; $c <= count($this->data['contact']); ++$c) {
888 $num = wf_crm_aval($this->data, "membership:{$c}:number_of_membership", 0);
889 $this->form['membership'][$c]["membership_{$c}_number_of_membership"] = array(
891 '#title' => t('Number of Memberships for !contact', array('!contact' => wf_crm_contact_label($c, $this->data, 'wrap'))),
892 '#default_value' => $num,
893 '#options' => range(0, 9),
894 '#prefix' => '<div class="number-of">',
895 '#suffix' => '</div>',
897 $this->addAjaxItem("membership:$c", "membership_{$c}_number_of_membership", "membership");
898 for ($n = 1; $n <= $num; ++$n) {
899 $fs = "membership_{$c}_membership_{$n}_fieldset";
900 $this->form['membership'][$c]['membership'][$fs] = array(
901 '#type' => 'fieldset',
902 '#title' => t('Membership !num for !contact', array('!num' => $n, '!contact' => wf_crm_contact_label($c, $this->data, 'wrap'))),
903 '#attributes' => array('id' => $fs, 'class' => array('web-civi-checkbox-set')),
904 'js_select' => $this->addToggle($fs),
906 foreach ($this->sets as $sid => $set) {
907 if ($set['entity_type'] == 'membership') {
908 foreach ($set['fields'] as $fid => $field) {
909 $fid = "civicrm_{$c}_membership_{$n}_$fid";
910 $this->form['membership'][$c]['membership'][$fs][$fid] = $this->addItem($fid, $field);
919 * Contribution settings
921 private function buildContributionTab() {
922 $this->form['contribution'] = array(
923 '#type' => 'fieldset',
924 '#title' => t('Contribution'),
925 '#group' => 'webform_civicrm',
926 '#description' => t('In order to process live transactions for events, memberships, or contributions, select a contribution page and its billing fields will be included on the webform.'),
927 '#attributes' => array('class' => array('civi-icon-contribution')),
929 $fid = 'civicrm_1_contribution_1_contribution_contribution_page_id';
930 $this->form['contribution'][$fid] = $this->addItem($fid, $this->fields['contribution_contribution_page_id']);
931 unset($this->sets['contribution']['fields']['contribution_contribution_page_id']);
932 $this->addAjaxItem('contribution', $fid, 'sets');
933 $page_id = wf_crm_aval($this->data, 'contribution:1:contribution:1:contribution_page_id');
935 $page = wf_civicrm_api('contribution_page', 'getsingle', array('id' => $page_id));
937 if (!$page_id || empty($page['financial_type_id'])) {
940 // Make sure webform is set-up to prevent credit card abuse.
941 $this->checkSubmissionLimit();
942 // Add contribution fields
943 foreach ($this->sets as $sid => $set) {
944 if ($set['entity_type'] == 'contribution' && (empty($set['sub_types']) || $set['sub_types'][0] == $page['financial_type_id'])) {
945 $this->form['contribution']['sets'][$sid] = array(
946 '#type' => 'fieldset',
947 '#title' => $set['label'],
948 '#attributes' => array('id' => $sid, 'class' => array('web-civi-checkbox-set')),
949 'js_select' => $this->addToggle($sid),
951 foreach ($set['fields'] as $fid => $field) {
952 $fid = "civicrm_1_contribution_1_$fid";
953 $this->form['contribution']['sets'][$sid][$fid] = $this->addItem($fid, $field);
961 * FIXME: This is nearly the same code as buildCaseTab. More utilities and less boilerplate needed.
963 private function buildGrantTab() {
964 $types = wf_crm_apivalues('grant', 'getoptions', array('field' => 'grant_type_id'));
968 $this->form['grantTab'] = array(
969 '#type' => 'fieldset',
970 '#title' => t('Grants'),
971 '#group' => 'webform_civicrm',
972 '#attributes' => array('class' => array('civi-icon-grant')),
974 $this->form['grantTab']["grant_number_of_grant"] = array(
976 '#title' => t('Number of Grants'),
977 '#default_value' => $num = wf_crm_aval($this->data, "grant:number_of_grant", 0),
978 '#options' => range(0, $this->sets['grant']['max_instances']),
979 '#prefix' => '<div class="number-of">',
980 '#suffix' => '</div>',
982 $this->addAjaxItem("grantTab", "grant_number_of_grant", "grant");
983 for ($n = 1; $n <= $num; ++$n) {
984 $fs = "grant_grant_{$n}_fieldset";
985 $this->form['grantTab']['grant'][$fs] = array(
986 '#type' => 'fieldset',
987 '#title' => t('Grant !num', array('!num' => $n)),
988 'wrap' => array('#weight' => 9),
990 $this->form['grantTab']['grant'][$fs]["grant_{$n}_settings_existing_grant_status"] = array(
992 '#title' => t('Update Existing Grant'),
993 '#options' => array('' => '- ' . t('None') . ' -') + wf_crm_apivalues('grant', 'getoptions', array('field' => 'status_id')),
994 '#default_value' => wf_crm_aval($this->data, "grant:{$n}:existing_grant_status", array()),
997 $this->help($this->form['grantTab']['grant'][$fs]["grant_{$n}_settings_existing_grant_status"], 'existing_grant_status');
998 $grant_type = wf_crm_aval($this->data, "grant:{$n}:grant:1:grant_type_id");
999 foreach ($this->sets as $sid => $set) {
1000 if ($set['entity_type'] == 'grant' && (!$grant_type || empty($set['sub_types']) || in_array($grant_type, $set['sub_types']))) {
1001 $fs1 = "grant_grant_{$n}_fieldset_$sid";
1002 if ($sid == 'grant') {
1003 $pos = &$this->form['grantTab']['grant'][$fs];
1006 $pos = &$this->form['grantTab']['grant'][$fs]['wrap'];
1009 '#type' => 'fieldset',
1010 '#title' => $set['label'],
1011 '#attributes' => array('id' => $fs1, 'class' => array('web-civi-checkbox-set')),
1012 'js_select' => $this->addToggle($fs1),
1014 foreach ($set['fields'] as $fid => $field) {
1015 $fid = "civicrm_{$n}_grant_1_$fid";
1016 $pos[$fs1][$fid] = $this->addItem($fid, $field);
1020 $this->addAjaxItem("grantTab:grant:$fs:grant_grant_{$n}_fieldset_grant", "civicrm_{$n}_grant_1_grant_grant_type_id", "..:wrap");
1025 * Configure additional options
1027 private function buildOptionsTab() {
1028 $this->form['options'] = array(
1029 '#type' => 'fieldset',
1030 '#title' => t('Additional Options'),
1031 '#group' => 'webform_civicrm',
1032 '#attributes' => array('class' => array('civi-icon-prefs')),
1033 '#description' => '<p>' .
1034 t('To have this form auto-filled for anonymous users, enable the "Existing Contact" field for !contact and send the following link from CiviMail:', array('!contact' => wf_crm_contact_label(1, $this->data, TRUE))) .
1035 '<br /><code>' . url("node/{$this->node->nid}", array('absolute' => TRUE, 'query' => array('cid1' => ''))) . '{contact.contact_id}&{contact.checksum}</code></p>',
1037 $this->form['options']['create_fieldsets'] = array(
1038 '#type' => 'checkbox',
1039 '#title' => t('Create Fieldsets'),
1040 '#default_value' => (bool) $this->settings['create_fieldsets'],
1041 '#description' => t('Create a fieldset around each contact. Provides visual organization of your form. Also allows the contact clone feature to work.'),
1043 $this->form['options']['confirm_subscription'] = array(
1044 '#type' => 'checkbox',
1045 '#title' => t('Confirm Subscriptions'),
1046 '#default_value' => (bool) $this->settings['confirm_subscription'],
1047 '#description' => t('Recommended. Send a confirmation email before adding contacts to publicly subscribable mailing list groups.') . '<br />' . t('Your public mailing lists:') . ' <em>',
1049 $ml = wf_crm_apivalues('group', 'get', array('is_hidden' => 0, 'visibility' => 'Public Pages', 'group_type' => 2), 'title');
1051 if (count($ml) > 4) {
1052 $ml = array_slice($ml, 0, 3);
1055 $this->form['options']['confirm_subscription']['#description'] .= implode(', ', $ml) . '</em>';
1058 $this->form['options']['confirm_subscription']['#description'] .= t('none') . '</em>';
1060 $this->form['options']['block_unknown_users'] = array(
1061 '#type' => 'checkbox',
1062 '#title' => t('Block Unknown Users'),
1063 '#default_value' => !empty($this->settings['block_unknown_users']),
1064 '#description' => t('Only allow users to see this form if they are logged in or following a personalized link from CiviMail.'),
1066 $this->form['options']['new_contact_source'] = array(
1067 '#type' => 'textfield',
1068 '#title' => t('Source Label'),
1069 '#maxlength' => 255,
1071 '#default_value' => $this->settings['new_contact_source'],
1072 '#description' => t('Optional "source" label for any new contact/participant/membership created by this webform.'),
1076 private function checkSubmissionLimit() {
1077 $webform = &$this->node->webform;
1078 // If anonymous users don't have access to the form, no need for a warning.
1079 if (!in_array('1', $webform['roles'])) {
1082 // Handle ajax submission from "submit_limit" mini-form below
1083 if (!empty($_POST['submit_limit']) && !empty($_POST['submit_interval'])) {
1084 $submit_limit = (int) $_POST['submit_limit'];
1085 $submit_interval = (int) $_POST['submit_interval'];
1086 if ($submit_limit > 0 && $submit_interval != 0) {
1087 $webform['submit_limit'] = $submit_limit;
1088 $webform['submit_interval'] = $submit_interval;
1089 db_update('webform')
1090 ->condition('nid', $this->node->nid)
1091 ->fields(array('submit_limit' => $submit_limit, 'submit_interval' => $submit_interval))
1094 drupal_set_message(t('Per-user submission limit has been updated. You may revisit these options any time on the <em>Form Settings</em> tab of this webform.'));
1096 // Handle ajax submission from "webform_tracking_mode" mini-form below
1097 if (!empty($_POST['webform_tracking_mode']) && $_POST['webform_tracking_mode'] == 'strict') {
1098 variable_set('webform_tracking_mode', 'strict');
1099 drupal_set_message(t('Webform anonymous user tracking has been updated to use the strict method. You may revisit this option any time on the global <a !link>Webform Settings</a> page.',
1100 array('!link' => 'href="/admin/config/content/webform" target="_blank"')
1103 // Mini-form to configure submit limit without leaving the page
1104 if ($webform['submit_limit'] == -1) {
1105 $this->form['contribution']['sets']['submit_limit'] = array(
1106 '#markup' => '<div class="messages warning">' .
1107 t('To prevent Credit Card abuse, it is recommended to set the per-user submission limit for this form.') .
1108 ' <button id="configure-submit-limit" type="button">' . t('Configure') . '</button>' .
1109 '<div id="submit-limit-wrapper" style="display:none">' .
1110 t('Limit each user to') .
1111 ' <input class="form-text" type="number" maxlength="2" size="2" name="submit_limit"> ' .
1112 t('submission(s)') . ' <select class="form-select" name="submit_interval">' .
1113 '<option value="-1">' .t('ever') . '</option>' .
1114 '<option value="3600" selected="selected">' .t('every hour') . '</option>' .
1115 '<option value="86400">' .t('every day') . '</option>' .
1116 '<option value="604800">' .t('every week') . '</option>'.
1117 '</select> ' .
1118 ' <button id="configure-submit-limit-save" type="button">' . t('Save') . '</button>' .
1119 ' <button id="configure-submit-limit-cancel" type="button">' . t('Cancel') . '</button>' .
1124 // Mini-form to conveniently update global cookie setting
1125 elseif (variable_get('webform_tracking_mode', 'cookie') == 'cookie') {
1126 $this->form['contribution']['sets']['webform_tracking_mode'] = array(
1127 '#markup' => '<div class="messages warning">' .
1128 t('Per-user submission limit is enabled for this form, however the webform anonymous user tracking method is configured to use cookies only, which is not secure enough to prevent Credit Card abuse.') .
1129 ' <button id="webform-tracking-mode" type="button">' . t('Change Now') . '</button>' .
1130 ' <input type="hidden" value="" name="webform_tracking_mode"> ' .
1137 * Set defaults when visiting the civicrm tab for the first time
1139 private function defaultSettings() {
1146 'contact_type' => 'individual',
1147 'contact_sub_type' => array(),
1152 'reg_options' => array(
1156 'confirm_subscription' => 1,
1157 'create_fieldsets' => 1,
1158 'new_contact_source' => check_plain($this->node->title),
1159 'civicrm_1_contact_1_contact_first_name' => 'create_civicrm_webform_element',
1160 'civicrm_1_contact_1_contact_last_name' => 'create_civicrm_webform_element',
1161 'civicrm_1_contact_1_contact_existing' => 'create_civicrm_webform_element',
1166 * Build a field item for the admin form
1168 * @param string $fid
1170 * @param array $field
1171 * Webform field info
1174 * FAPI form item array for the admin form
1176 private function addItem($fid, $field) {
1177 list(, $c, $ent, $n, $table, $name) = explode('_', $fid, 6);
1179 // We don't need numbers on the admin form since they are already grouped in fieldsets
1180 '#title' => str_replace('#', '', $field['name']),
1181 '#attributes' => wf_crm_aval($field, 'attributes'),
1184 // Create dropdown list
1185 if (!empty($field['expose_list'])) {
1186 $field['form_key'] = $fid;
1187 // Retrieve option list
1189 // Placeholder empty option - used by javascript when displaying multiselect as single
1190 if (!empty($field['extra']['multiple']) && empty($field['extra']['required'])) {
1191 $options += array('' => '- ' . t('None') . ' -');
1193 // This prevents the multi-select js from adding an illegal empty option
1194 if (!empty($field['extra']['required'])) {
1195 $item['#attributes']['class'][] = 'required';
1197 if ($field['type'] != 'hidden') {
1198 $options += array('create_civicrm_webform_element' => t('- User Select -'));
1200 $options += wf_crm_field_options($field, 'config_form', $this->data);
1202 '#type' => 'select',
1203 '#options' => $options,
1204 '#multiple' => !empty($field['extra']['multiple']),
1205 '#default_value' => !empty($field['empty_option']) ? 0 : NULL,
1207 if (isset($field['empty_option'])) {
1208 $item['#empty_option'] = '- ' . $field['empty_option'] . ' -';
1209 $item['#empty_value'] = 0;
1211 if (isset($field['data_type'])) {
1212 $item['#attributes']['data-type'] = $field['data_type'];
1214 // Five ways to get default value...
1215 // 1: From current form state
1216 if (isset($this->settings[$fid]) && ($field['type'] != 'hidden')) {
1217 $item['#default_value'] = $this->settings[$fid];
1219 // 2: From saved settings
1220 elseif (isset($this->data[$ent][$c][$table][$n][$name])) {
1221 $item['#default_value'] = $this->data[$ent][$c][$table][$n][$name];
1223 // 3: From callback function
1224 elseif (isset($field['value_callback'])) {
1225 $method = 'get_default_' . $table . '_' . $name;
1226 $item['#default_value'] = self::$method($fid, $options);
1228 // 4: From field default
1229 elseif (isset($field['value'])) {
1230 $item['#default_value'] = $field['value'];
1232 // 5: For required fields like phone type, default to the first option
1233 elseif (empty($field['extra']['multiple']) && !isset($field['empty_option'])) {
1234 $options = array_keys($options);
1235 $item['#default_value'] = $options[1];
1237 if (!empty($field['extra']['multiple'])) {
1238 $item['#default_value'] = (array) $item['#default_value'];
1239 if (isset($this->settings[$fid]) && !is_array($this->settings[$fid])
1240 && isset($this->data[$ent][$c][$table][$n][$name])) {
1241 $item['#default_value'] += (array) $this->data[$ent][$c][$table][$n][$name];
1248 '#type' => 'checkbox',
1249 '#return_value' => 'create_civicrm_webform_element',
1250 '#default_value' => !empty($this->settings[$fid]),
1254 $topic = $table . '_' . $name;
1255 if (method_exists('wf_crm_admin_help', $topic)) {
1256 $this->help($item, $topic);
1258 elseif (!empty($field['has_help'])) {
1259 $this->help($item, $name);
1261 elseif (wf_crm_aval($field, 'data_type') == 'ContactReference') {
1262 $this->help($item, 'contact_reference');
1264 elseif (!empty($field['expose_list']) && !empty($field['extra']['multiple'])) {
1265 $this->help($item, 'multiselect_options', t('Multiple Select Options'));
1271 * Boilerplate-reducing helper function for FAPI ajax.
1272 * Set an existing form element to control an ajax container.
1273 * The container will be created if it doesn't already exist.
1275 * @param string $path
1276 * A : separated string of nested array keys leading to the control element's parent
1277 * @param string $control_element
1278 * Array key of the existing element to add ajax behavior to
1279 * @param string $container
1280 * Path to the key of the container to be created (relative to $path) use '..' to go up a level
1281 * @param string $class
1282 * Css class to add to target container
1284 private function addAjaxItem($path, $control_element, $container, $class='civicrm-ajax-wrapper') {
1285 // Get a reference to the control container
1286 // For anyone who wants to call this evil - I challenge you to find a better way to accomplish this
1287 eval('$control_container = &$this->form[\'' . str_replace(':', "']['", $path) . "'];");
1288 // Now find the container element (may be outside the $path if .. is used)
1289 foreach (explode(':', $container) as $level) {
1290 if ($level == '..') {
1291 $path = substr($path, 0, strrpos($path, ':'));
1294 $path .= ':' . $level;
1297 eval('$target_container = &$this->form[\'' . str_replace(':', "']['", substr($path, 0, strrpos($path, ':'))) . "'];");
1298 $id = 'civicrm-ajax-' . str_replace(array(':', '_'), '-', $path);
1299 $control_container[$control_element]['#ajax'] = array(
1300 'callback' => 'wf_crm_configure_form_ajax',
1305 if (!isset($target_container[$level])) {
1306 $target_container[$level] = array();
1308 $target_container[$level]['#prefix'] = '<div class="' . $class . '" id="' . $id . '">';
1309 $target_container[$level]['#suffix'] = '</div>';
1313 * Build select all/none js links for a fieldset
1315 private function addToggle($name) {
1316 return array('#markup' =>
1317 '<div class="web-civi-js-select">
1318 <a href="javascript:wfCiviAdmin.selectReset(' . "'all', '#$name'" . ')">' . t('Select All') . '</a> |
1319 <a href="javascript:wfCiviAdmin.selectReset(' . "'none', '#$name'" . ')">' . t('Select None') . '</a> |
1320 <a href="javascript:wfCiviAdmin.selectReset(' . "'reset', '#$name'" . ')">' . t('Restore') . '</a>
1326 * Build $this->data array for webform settings; called while rebuilding or post-processing the admin form.
1328 private function rebuildData() {
1329 $this->settings['data'] = array('contact' => array());
1330 $this->data = &$this->settings['data'];
1331 list($contact_types, $sub_types) = wf_crm_get_contact_types();
1332 for ($c = 1; $c <= $this->settings['number_of_contacts']; ++$c) {
1334 if (isset($this->settings[$c . '_contact_type'])) {
1335 $this->data['contact'][$c] = array(
1336 'contact' => array(1 => array(
1337 'contact_type' => $this->settings[$c . '_contact_type'],
1338 'contact_sub_type' => array(),
1339 'webform_label' => $this->settings[$c . '_webform_label'],
1342 if ($sub_type = wf_crm_aval($this->settings, 'civicrm_' . $c . '_contact_1_contact_contact_sub_type')) {
1343 $allowed = wf_crm_aval($sub_types, $this->settings[$c . '_contact_type'], array());
1344 foreach ($sub_type as $sub) {
1345 if (isset($allowed[$sub])) {
1346 $this->data['contact'][$c]['contact'][1]['contact_sub_type'][$sub] = $sub;
1351 // Add new contact to the form
1353 $this->data['contact'][$c] = array(
1354 'contact' => array(1 => array(
1355 'contact_type' => 'individual',
1356 'contact_sub_type' => array(),
1358 'matching_rule' => 'Unsupervised',
1360 // Set defaults for new contact
1361 $this->settings += array(
1362 'civicrm_' . $c . '_contact_1_contact_first_name' => 'create_civicrm_webform_element',
1363 'civicrm_' . $c . '_contact_1_contact_last_name' => 'create_civicrm_webform_element',
1365 $link = array('!link' => 'href="http://wiki.civicrm.org/confluence/display/CRMDOC/Webform+CiviCRM+Integration#WebformCiviCRMIntegration-CloningaContact" target="_blank"');
1366 drupal_set_message(t('Tip: Consider using the clone feature to add multiple similar contacts. (<a !link>more info</a>)', $link), 'status', FALSE);
1369 // Store meta settings, i.e. number of email for contact 1
1370 foreach ($this->settings as $key => $val) {
1371 if (strpos($key, '_number_of_') !== FALSE) {
1372 list($ent, $c, $key) = explode('_', $key, 3);
1373 if (isset($this->data[$ent][$c]) || $ent == 'participant' || $ent == 'membership') {
1374 $this->data[$ent][$c][$key] = $val;
1376 // Standalone entities keep their own count independent of contacts
1377 elseif ($ent == 'grant' || $ent == 'activity' || $ent == 'case') {
1378 $this->data[$ent]["number_$key"] = $val;
1381 elseif (strpos($key, '_settings_') !== FALSE) {
1382 list($ent, $c, , $key) = explode('_', $key, 4);
1383 $val = is_array($val) ? array_filter($val) : $val;
1384 // Don't store settings for nonexistant contacts. Todo: check other entities
1385 if (isset($this->data[$ent][$c]) || $ent !== 'contact') {
1386 $this->data[$ent][$c][$key] = $val;
1390 // Defaults when adding an activity
1391 for ($i=1; $i <= $this->settings['activity_number_of_activity']; ++$i) {
1392 if (!isset($this->settings["activity_{$i}_settings_existing_activity_status"])) {
1393 $this->data['activity'][$i]['activity'][1]['target_contact_id'] = range(1, $this->settings['number_of_contacts']);
1396 // Defaults when adding a case
1397 for ($i=1; $i <= wf_crm_aval($this->settings, 'case_number_of_case'); ++$i) {
1398 if (!isset($this->settings["civicrm_{$i}_case_1_case_case_type_id"])) {
1399 $case_types = array_keys(wf_crm_apivalues('Case', 'getoptions', array('field' => 'case_type_id')));
1400 $this->data['case'][$i]['case'][1]['case_type_id'] = $case_types[0];
1403 // Store event settings
1404 if (isset($this->settings['participant_reg_type'])) {
1405 $this->data['participant_reg_type'] = $this->settings['participant_reg_type'];
1406 $this->data['reg_options'] = $this->settings['reg_options'];
1408 // Add settings exposed to the back-end to data
1409 foreach ($this->settings as $key => $val) {
1410 if (substr($key, 0, 7) == 'civicrm') {
1411 list(, $c, $ent, $n, $table, $name) = explode('_', $key, 6);
1412 if (is_array($val)) {
1413 // Git rid of the "User Select" and "None" options
1414 unset($val['create_civicrm_webform_element'], $val['']);
1416 elseif ($val === 'create_civicrm_webform_element') {
1419 // Saves all non-empty values with a hack for fields which needs to be saved even when 0
1420 // FIXME: Really ought to change the select placeholder value to be '' instead of 0
1421 if (isset($this->fields[$table . '_' . $name]['expose_list']) &&
1422 (!empty($val) || (in_array($name, array('num_terms', 'is_active', 'is_test'))))) {
1423 // Don't add data for non-existent contacts
1424 if (!in_array($ent, array('contact', 'participant', 'membership')) || isset($this->data['contact'][$c])) {
1425 $this->data[$ent][$c][$table][$n][$name] = $val;
1433 * Submission handler, saves CiviCRM options for a Webform node
1435 public function postProcess() {
1436 $button = $this->form_state['clicked_button']['#id'];
1437 $nid = $this->node->nid;
1438 $this->settings = wf_crm_aval($this->form_state, 'storage:vals', $this->form_state['values']);
1440 if ((empty($this->node->webform_civicrm) && !$this->settings['nid']) || $button == 'edit-cancel') {
1441 $this->form_state['rebuild'] = TRUE;
1442 unset($this->form_state['storage']['msg']);
1445 unset($this->form_state['storage']);
1447 $enabled = $existing = wf_crm_enabled_fields($this->node, NULL, TRUE);
1448 $delete_me = $this->getFieldsToDelete($enabled);
1450 // Display a confirmation before deleting fields
1451 if ($delete_me && $button == 'edit-submit') {
1452 $msg = '<p>' . t('These existing fields are no longer needed for CiviCRM processing based on your new form settings.') . '</p><ul>';
1453 foreach ($delete_me as $key => $id) {
1454 list(, $c, $ent, $n, $table, $name) = explode('_', $key, 6);
1456 if ($ent == 'contact' || $ent == 'participant') {
1457 $info = '<em>' . wf_crm_contact_label($c, wf_crm_aval($this->node, 'webform_civicrm:data'));
1459 if ($info && isset($this->sets[$table]['max_instances'])) {
1460 $info .= ' ' . $this->sets[$table]['label'] . ' ' . $n;
1462 $info .= $info ? ':</em> ' : '';
1463 $msg .= '<li>' . $info . $this->node->webform['components'][$id]['name'] . '</li>';
1465 $msg .= '</ul><p>' . t('Would you like them to be automatically removed from the webform? This is recommended unless you need to keep webform-results information from these fields. (They can still be deleted manually later if you choose not to remove them now.)') . '</p><p><em>' . t('Note: Deleting webform components cannot be undone, and will result in the loss of webform-results info for those elements. Data in the CiviCRM database will not be affected.') . '</em></p>';
1466 $this->form_state['storage']['msg'] = $msg;
1467 $this->form_state['storage']['vals'] = $this->settings;
1468 $this->form_state['rebuild'] = TRUE;
1472 module_load_include('inc', 'webform', 'includes/webform.components');
1473 module_load_include('inc', 'webform_civicrm', 'includes/contact_component');
1474 $this->form_state['redirect'] = 'node/' . $nid . '/webform';
1476 // Delete/disable fields
1478 if ($button === 'edit-delete' || ($button === 'edit-disable' && $this->settings['nid'])) {
1479 foreach ($delete_me as $id) {
1480 $field = $this->node->webform['components'][$id];
1481 unset($enabled[$field['form_key']]);
1483 if ($button === 'edit-delete') {
1484 webform_component_delete($this->node, $field);
1487 $field['form_key'] = 'disabled' . substr($field['form_key'], 7);
1488 webform_component_update($field);
1491 if ($deleted == 1) {
1492 $p = array('%name' => $field['name']);
1493 drupal_set_message($button === 'edit-delete' ? t('Deleted field: %name', $p) : t('Disabled field: %name', $p));
1496 $p = array('!num' => $deleted);
1497 drupal_set_message($button === 'edit-delete' ? t('Deleted !num fields.', $p) : t('Disabled !num fields.', $p));
1499 if ($button === 'edit-disable') {
1500 drupal_set_message(t('Disabled fields will still be processed as normal Webform fields, but they will not be autofilled from or saved to the CiviCRM database.'));
1503 // Remove empty fieldsets for deleted contacts
1504 foreach ($enabled as $key => $id) {
1505 if (substr($key, -8) == 'fieldset') {
1506 list(, $c, $ent, $i) = explode('_', $key);
1507 if ($ent == 'contact' && $i == 1 && (!$this->settings['nid'] || $c > $this->settings['number_of_contacts'])) {
1508 if (!_wf_crm_child_components($this->node->nid, $id)) {
1509 webform_component_delete($this->node, $this->node->webform['components'][$id]);
1517 // Disable CiviCRM for this form
1518 if (!$this->settings['nid']) {
1520 drupal_set_message(t('CiviCRM processing for this form is now disabled.'));
1525 webform_ensure_record($this->node);
1526 $this->rebuildData();
1527 if (!$this->settings['toggle_message']) {
1528 $this->settings['message'] = '';
1530 // Index disabled components
1531 $disabled = array();
1532 foreach (wf_crm_aval($this->node->webform, 'components', array()) as $field) {
1533 if (substr($field['form_key'], 0, 9) === 'disabled_') {
1534 $field['form_key'] = 'civicrm' . substr($field['form_key'], 8);
1535 $disabled[$field['form_key']] = $field;
1541 foreach ($this->settings as $key => $val) {
1542 if (substr($key, 0, 7) == 'civicrm') {
1544 $field = wf_crm_get_field($key);
1545 if (!isset($enabled[$key])) {
1546 $val = (array) $val;
1547 if (in_array('create_civicrm_webform_element', $val, TRUE) || (!empty($val[0]) && $field['type'] == 'hidden')) {
1548 // Restore disabled component
1549 if (isset($disabled[$key])) {
1550 webform_component_update($disabled[$key]);
1551 $enabled[$key] = $disabled[$key]['cid'];
1552 drupal_set_message(t('Re-enabled field: %name', array('%name' => $disabled[$key]['name'])));
1554 // Create new component
1561 self::insertComponent($field, $enabled, $this->settings);
1562 $created[] = $field['name'];
1563 if (isset($field['civicrm_condition'])) {
1564 $this->addConditionalRule($field, $enabled);
1569 elseif ($field['type'] == 'hidden' && !empty($field['expose_list'])) {
1570 $component = $this->node->webform['components'][$enabled[$key]];
1571 $component['value'] = $val;
1572 webform_component_update($component);
1576 if (count($created) == 1) {
1577 drupal_set_message(t('Added field: %name', array('%name' => $created[0])));
1580 drupal_set_message(t('Added !num fields to the form.', array('!num' => count($created))));
1584 if (empty($this->node->webform_civicrm)) {
1585 drupal_write_record('webform_civicrm_forms', $this->settings);
1586 drupal_set_message(t('CiviCRM processing for this form is now enabled.'));
1590 drupal_write_record('webform_civicrm_forms', $this->settings, 'nid');
1591 drupal_set_message(t('Your CiviCRM form settings have been updated.'));
1593 // Update existing contact fields
1594 foreach ($existing as $fid => $id) {
1595 if (substr($fid, -8) === 'existing') {
1596 wf_crm_update_existing_component($this->node->webform['components'][$id], $enabled, $this->data);
1600 // Make sure the updates are visible to anonymous users.
1603 // Clear the entity cache.
1604 if (module_exists('entitycache')) {
1605 cache_clear_all($nid, 'cache_entity_node');
1610 * Create a conditional rule if the source and target fields both exist.
1611 * TODO: This is fairly minimal. It doesn't check if the rule already exists,
1612 * and doesn't work if both fields haven't been created yet.
1614 * @param array $field
1615 * @param array $enabled
1617 private function addConditionalRule($field, $enabled) {
1618 list(, $c, $ent, $n, $table, $name) = explode('_', $field['form_key'], 6);
1619 $rgid = $weight = -1;
1620 foreach ($this->node->webform['conditionals'] as $rgid => $existing) {
1621 $weight = $existing['weight'];
1624 $rule_group = $field['civicrm_condition'] + array(
1625 'nid' => $this->node->nid,
1627 'weight' => $weight,
1628 'target' => $enabled[$field['form_key']],
1629 'target_type' => 'component',
1631 $rule_group['rules'] = array();
1632 foreach ($field['civicrm_condition']['rules'] as $source => $conditions) {
1633 $source_key = "civicrm_{$c}_{$ent}_{$n}_{$source}";
1634 $source_id = wf_crm_aval($enabled, $source_key);
1636 $options = wf_crm_field_options(array('form_key' => $source_key), '', $this->settings['data']);
1637 foreach ($conditions as $condition) {
1638 if (isset($options[$condition])) {
1639 $rule_group['rules'][] = array(
1640 'source_type' => 'component',
1641 'source' => $source_id,
1642 'operator' => 'equal',
1643 'value' => $condition,
1649 if ($rule_group['rules']) {
1650 $this->node->webform['conditionals'][] = $rule_group;
1651 module_load_include('inc', 'webform', 'includes/webform.conditionals');
1652 webform_conditional_insert($rule_group);
1656 private function help(&$field, $topic, $title = NULL) {
1657 wf_crm_admin_help::addHelp($field, $topic, $title);
1661 * Search for fields that should be deleted
1662 * @param array $fields
1665 private function getFieldsToDelete($fields) {
1666 // Find fields to delete
1667 foreach ($fields as $key => $val) {
1668 $val = (array) wf_crm_aval($this->settings, $key);
1669 if (((in_array('create_civicrm_webform_element', $val, TRUE)) && $this->settings['nid'])
1670 || strpos($key, 'fieldset') !== FALSE) {
1671 unset($fields[$key]);
1674 $field = wf_crm_get_field($key);
1675 if (!empty($val[0]) && $field['type'] == 'hidden') {
1676 unset($fields[$key]);
1684 * Add a CiviCRM field to a webform
1686 * @param $field: array
1687 * Webform field info
1688 * @param $enabled: array
1689 * Array of enabled fields (reference)
1691 * webform_civicrm configuration for this form
1693 static function insertComponent(&$field, &$enabled, $settings) {
1695 list(, $c, $ent, $n, $table, $name) = explode('_', $field['form_key'], 6);
1696 $contact_type = $settings['data']['contact'][$c]['contact'][1]['contact_type'];
1697 // Replace the # token with set number (or append to the end if no token)
1699 if (strpos($field['name'], '#') === FALSE) {
1700 $field['name'] .= " $n";
1703 $field['name'] = str_replace('#', $n, $field['name']);
1706 elseif ($table == 'relationship') {
1707 $field['name'] = t('Relationship to !contact', array('!contact' => wf_crm_contact_label($n, $settings['data']))) . ' ' . $field['name'];
1710 $field['name'] = str_replace(' #', '', $field['name']);
1712 if ($name == 'contact_sub_type') {
1713 list($contact_types) = wf_crm_get_contact_types();
1714 $field['name'] = t('Type of @contact', array('@contact' => $contact_types[$contact_type]));
1716 // Defaults for existing contact field
1717 if ($name == 'existing') {
1718 $vals = $enabled + $settings;
1719 // Set the allow_create flag based on presence of name or email fields
1720 $field['extra']['allow_create'] = $a = wf_crm_name_field_exists($vals, $c, $contact_type);
1721 $field['extra']['none_prompt'] = $a ? t('+ Create new +') : t('- None Found -');
1722 if ($c == 1 && $contact_type == 'individual') {
1723 // Default to hidden field for 1st contact
1724 $field['extra'] += array(
1725 'widget' => 'hidden',
1726 'default' => 'user',
1730 // A width of 20 is more sensible than Drupal's default of 60
1731 if (($field['type'] == 'textfield' || $field['type'] == 'email') && empty($field['extra']['width'])) {
1732 $field['extra']['width'] = 20;
1734 // Support html_textarea module
1735 if ($field['type'] == 'html_textarea') {
1736 $field['value']['format'] = filter_default_format();
1737 $field['value']['value'] = '';
1739 // Retrieve option list
1740 if ($field['type'] == 'select') {
1741 if ($options = wf_crm_field_options($field, 'component_insert', $settings['data'])) {
1742 $field['extra']['items'] = wf_crm_array2str($options);
1743 // Default to select widget
1744 if (!isset($field['extra']['aslist']) && empty($field['extra']['multiple'])) {
1745 $field['extra']['aslist'] = 1;
1747 // A single static radio should be shown as a checkbox
1748 if (count($options) == 1 && empty($field['extra']['aslist']) && empty($field['extra']['civicrm_live_options'])) {
1749 $field['extra']['multiple'] = 1;
1753 if (isset($field['value_callback'])) {
1754 $method = 'get_default_' . $table . '_' . $name;
1755 $field['value'] = self::$method($field['form_key'], $options);
1757 // For hidden+select fields such as contribution_page
1758 if ($field['type'] == 'hidden' && !empty($field['expose_list']) && !empty($settings[$field['form_key']])) {
1759 $field['value'] = $settings[$field['form_key']];
1761 // Create fieldsets - for contact and contact-specific event fields only
1762 if ($ent != 'activity' && $ent != 'case' && $ent != 'contribution' && $ent != 'grant'
1763 && ($ent != 'participant' || wf_crm_aval($settings['data'], 'participant_reg_type') == 'separate')) {
1764 self::addFieldset($c, $field, $enabled, $settings);
1766 // Create page break for contribution page
1767 if ($name == 'contribution_page_id') {
1768 self::addPageBreak($field);
1770 // Merge defaults and create webform component
1771 $field += array('extra' => array());
1772 if ($defaults = webform_component_invoke($field['type'], 'defaults')) {
1773 $field += $defaults;
1775 if (isset($enabled[$field['form_key']])) {
1776 $field['cid'] = $enabled[$field['form_key']];
1777 webform_component_update($field);
1780 $enabled[$field['form_key']] = webform_component_insert($field);
1785 * Create a fieldset around a contact if it doesn't already exist
1791 static function addFieldset($c, &$field, &$enabled, $settings) {
1792 $sid = 'civicrm_' . $c . '_contact_1_fieldset_fieldset';
1793 if (!empty($settings['create_fieldsets']) && !isset($enabled[$sid])) {
1795 'nid' => $field['nid'],
1797 'type' => 'fieldset',
1798 'name' => wf_crm_contact_label($c, $settings['data']),
1801 $new_set += webform_component_invoke('fieldset', 'defaults');
1802 $enabled[$sid] = webform_component_insert($new_set);
1804 $field['pid'] = wf_crm_aval($enabled, $sid, 0);
1808 * Create a page-break before the contribution-page field
1811 static function addPageBreak($field) {
1812 $node = node_load($field['nid']);
1813 // Check if it already exists
1814 foreach (wf_crm_aval($node->webform, 'components', array()) as $component) {
1815 if ($component['form_key'] == 'contribution_pagebreak') {
1820 'nid' => $field['nid'],
1821 'form_key' => 'contribution_pagebreak',
1822 'type' => 'pagebreak',
1823 'name' => t('Payment'),
1824 'weight' => $field['weight'] - 9,
1826 $pagebreak += webform_component_invoke('pagebreak', 'defaults');
1827 webform_component_insert($pagebreak);
1831 * Default value callback
1833 static function get_default_contact_cs($fid, $options) {
1834 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'checksum_timeout', NULL, 7);
1838 * Default value callback
1840 static function get_default_contribution_payment_processor_id($fid, $options) {
1841 $default = wf_civicrm_api('payment_processor', 'get', array('is_default' => 1, 'is_test' => 0));
1842 if (!empty($default['id']) && isset($options[$default['id']])) {
1843 return $default['id'];
1846 return $options ? key($options) : 0;
1850 * Delete civicrm settings for this webform.
1852 private function disable() {
1853 db_delete('webform_civicrm_forms')
1854 ->condition('nid', $this->node->nid)
1858 private function contactRefOptions($exclude = NULL) {
1860 foreach ($this->data['contact'] as $num => $contact) {
1861 if ($num != $exclude) {
1862 $ret[$num] = wf_crm_contact_label($num, $this->data, 'plain');
1870 * Drupal FAPI form builder callback
1872 function wf_crm_configure_form($form, &$form_state, $node) {
1873 $admin_form = new wf_crm_admin_form(array(), $form_state, $node);
1874 return $admin_form->buildForm();
1878 * Drupal FAPI submit callback
1880 function wf_crm_configure_form_submit($form, &$form_state) {
1881 $node = node_load($form_state['storage']['nid']);
1882 $admin_form = new wf_crm_admin_form($form, $form_state, $node);
1883 $admin_form->postProcess();
1887 * FAPI AJAX callback
1889 function wf_crm_configure_form_ajax($form, $form_state) {
1890 return wf_crm_aval($form, $form_state['triggering_element']['#ajax']['pathstr']);