You are here

eloqua_webform.module in Eloqua 7.2

Same filename and directory in other branches
  1. 7 eloqua_webform/eloqua_webform.module

File

eloqua_webform/eloqua_webform.module
View source
<?php

/**
 * @file
 * Eloqua Webform Integration Module
 *
 * Known Limitations:
 *  - No summary information from the form component page to list the field
 *    names.
 *  - Using the functionality on a multi-page form has undefined effects
 *    - Currently it will queue the submit data after each page, so a 4 page
 *      form will be posted to eloqua 4 times (once for each page)
 *
 * @package Eloqua
 */
module_load_include('inc', 'eloqua_webform');

// Load the cron functionality.
module_load_include('inc', 'eloqua_webform', 'eloqua_webform.cron');

/**
 * Implements hook_menu().
 */
function eloqua_webform_menu() {
  $items['node/%webform_menu/webform/eloqua'] = array(
    'title' => 'Eloqua',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'eloqua_webform_configure_form',
      1,
    ),
    'access callback' => 'node_access',
    'access arguments' => array(
      'update',
      1,
    ),
    'weight' => 1,
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
 * Implements hook_cron().
 */
function eloqua_webform_cron() {
  _eloqua_send_posts();
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * This function is reponsible for adding the form-id mapping values to the
 * Component add/edit page. Note: This isn't used for the fieldset type.
 */
function eloqua_webform_form_webform_component_edit_form_alter(&$form, $form_state) {
  if (!array_key_exists('build_info', $form_state) || !array_key_exists('args', $form_state['build_info']) || !array_key_exists(1, $form_state['build_info']['args'])) {
    return;
  }
  $component = $form_state['build_info']['args'][1];

  // Create the fieldset.
  $form['eloqua'] = array(
    '#type' => 'fieldset',
    '#title' => t('Eloqua'),
    '#tree' => TRUE,
  );

  // Check the field type. Some do not make sense as having a value to post to
  // Eloqua.
  $component_type = $component['type'];
  if (in_array($component_type, array(
    'fieldset',
    'pagebreak',
  ))) {

    // todo: Get this working
    $form['eloqua']['msg'] = array(
      '#markup' => t('This component type is not compatible with the Eloqua Module.'),
    );
    return;
  }
  else {
    $form['eloqua']['key'] = array(
      '#type' => 'textfield',
      '#default_value' => isset($component['extra']['eloqua']['key']) ? $component['extra']['eloqua']['key'] : '',
      '#title' => t('Eloqua Field Name'),
      '#description' => t('The eloqua field name if it contains symbols or characters not compatible with the defaults above. Leave empty to use the default above. Can not contain spaces.'),
      '#weight' => 0,
    );
    $form['eloqua']['query_name'] = array(
      '#type' => 'textfield',
      '#default_value' => isset($component['extra']['eloqua']['query_name']) ? $component['extra']['eloqua']['query_name'] : '',
      '#description' => t('If this value can be populated by a query parameter, the key that is to be used. Can only contain the characters a-z A-Z 0-9 and _.'),
      '#title' => t('Request Parameter Key'),
    );
    $form['#validate'][] = 'eloqua_webform_component_edit_form_validate';
  }
}

/**
 * Implements hook_webform_component_presave().
 */
function eloqua_webform_webform_component_presave(&$component) {
  if (array_key_exists('eloqua', $component) && isset($component['eloqua'])) {
    $component['extra']['eloqua'] = $component['eloqua'];
  }
}

/**
 * Validates the Eloqua field.
 *
 * @todo Make this less Western Centric. Get parameters should be able to accept
 * all Unicode code-points.
 */
function eloqua_webform_component_edit_form_validate($form, $form_state) {
  if (preg_match('![\\x00-\\x20 ]!', $form_state['values']['eloqua']['key'])) {
    form_set_error('eloqua][key', t('The Eloqua field key %field_key is invalid. Please do not include spaces.', array(
      '%field_key' => $form_state['values']['eloqua']['key'],
    )));
  }
  $values = $form_state['values'];
  if (!empty($values['eloqua']['query_name'])) {
    if (!preg_match('/^[a-zA-Z0-9_]+$/', $values['eloqua']['query_name'])) {
      form_set_error('eloqua][query_name', t('The query name provided can only contain the characters a-z A-Z 0-9 and underscore (_).'));
    }
  }
}

/**
 * Eloqua webform configure form.
 *
 * @see eloqua_webform_configure_form_submit()
 * @see eloqua_webform_configure_form_validate()
 */
function eloqua_webform_configure_form($form, $form_state, $webform_node) {

  // Load the form options from the database if available.
  $settings = new stdClass();
  if (!empty($webform_node->nid)) {
    $settings = eloqua_webform_load($webform_node->nid);
  }

  // Apply default settings.
  if (!isset($settings->{'is_active'})) {
    $settings->{'is_active'} = 0;
  }
  if (!isset($settings->{'form_name'})) {
    $settings->{'form_name'} = '';
  }
  if (!isset($settings->{'data'})) {
    $settings->{'data'} = new stdClass();
  }
  if (!isset($settings->{'data'}->process_every_page)) {
    $settings->{'data'}->process_every_page = 0;
  }
  $form['eloqua'] = array(
    '#type' => 'fieldset',
    '#title' => t('Eloqua'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    'elq_enabled' => array(
      '#type' => 'checkbox',
      '#default_value' => $settings->{'is_active'},
      '#description' => t('Whether this form is eloqua enabled'),
      '#title' => t('Enabled'),
    ),
    'elq_form_name' => array(
      '#type' => 'textfield',
      '#default_value' => $settings->{'form_name'},
      '#description' => t('The form name as it is defined in Eloqua'),
      '#title' => t('Eloqua Form Name'),
    ),
    'elq_process_every_page' => array(
      '#type' => 'checkbox',
      '#default_value' => $settings->{'data'}->process_every_page,
      '#description' => t('Process every page submit on a multi-page form, instead of one combined submit upon completion.'),
      '#title' => t('Process subpages separately'),
    ),
  );
  $form['nid'] = array(
    '#type' => 'hidden',
    '#value' => $webform_node->nid,
  );
  $form['save'] = array(
    '#type' => 'submit',
    '#submit' => array(
      'eloqua_webform_configure_form_submit',
    ),
    '#value' => t('Save'),
  );
  $form['#validate'][] = 'eloqua_webform_configure_form_validate';
  return $form;
}

/**
 * Form validation handler for eloqua_webform_configure_form().
 *
 * @see eloqua_webform_configure_form()
 * @see eloqua_webform_configure_form_submit()
 */
function eloqua_webform_configure_form_validate($form, $form_state) {
  $values = $form_state['values'];
  if ($values['elq_enabled']) {
    if (empty($values['elq_form_name'])) {
      form_set_error('elq_form_name', t('The Eloqua Form Name must be set if the form is to be eloqua-enabled. This can only contain the characters a-zA-Z and _'));
    }
  }
}

/**
 * Form submission handler for eloqua_webform_configure_form().
 *
 * @see eloqua_webform_configure_form()
 * @see eloqua_webform_configure_form_validate()
 */
function eloqua_webform_configure_form_submit($form, &$form_state) {

  // On a new form.
  $nid = $form_state['values']['nid'];
  $values = $form_state['values'];
  $webform = new stdClass();
  $webform->{'nid'} = $nid;
  $webform->{'is_active'} = $values['elq_enabled'];
  $webform->{'form_name'} = $values['elq_form_name'];
  $webform->{'data'} = (object) array(
    'process_every_page' => $values['elq_process_every_page'],
  );
  eloqua_webform_create($webform);
  drupal_set_message(t('The configuration options have been saved.'));
}

/**
 * Implements hook_form_alter().
 */
function eloqua_webform_form_alter(&$form, $form_state, $form_id) {

  // Add setting to allow for immediate posting.
  if ($form_id == 'eloqua_admin_form') {
    $form['webform'] = array(
      '#type' => 'fieldset',
      '#title' => t('Webform Settings'),
      '#description' => t('Webform / Eloqua integration.'),
      'eloqua_webform_process_submit' => array(
        '#type' => 'checkbox',
        '#title' => 'Immediately process submissions?',
        '#default_value' => variable_get('eloqua_webform_process_submit', ''),
      ),
    );
  }
  elseif (strstr($form_id, 'webform_client_form')) {
    if (!array_key_exists('#node', $form) || !is_object($form['#node']) || empty($form['#node']->nid)) {
      return;
    }
    $nid = $form['#node']->nid;
    $form_settings = (array) eloqua_webform_load($nid);

    // Check to see if the form exists.
    if (empty($form_settings) || !$form_settings['is_active']) {
      return;
    }

    // Check for QUERY parameter mappings to assign default values.
    _eloqua_form_url_map($form, $form['#node']->webform['components']);

    // Just shove everything into a container.
    $form['#submit'][] = 'eloqua_webform_submit';
    $form['eloqua'] = array();
    $process_every_page = is_object($form_settings['data']) && isset($form_settings['data']->process_every_page) ? $form_settings['data']->process_every_page : FALSE;
    $form['eloqua']['process_every_page'] = array(
      '#type' => 'value',
      '#value' => $process_every_page,
    );
    $form['eloqua']['elqFormName'] = array(
      '#type' => 'hidden',
      '#default_value' => (string) $form_settings['form_name'],
    );
    $form['eloqua']['elqSiteId'] = array(
      '#type' => 'hidden',
      '#default_value' => variable_get('eloqua_site_id', 0),
    );
    $form['eloqua']['elqDefaultTargetURL'] = array(
      '#type' => 'hidden',
      '#default_value' => '',
    );
    $form['eloqua']['elqPost'] = array(
      '#type' => 'hidden',
      '#default_value' => '',
    );
    $form['eloqua']['elqCustomerGUID'] = array(
      '#type' => 'hidden',
      '#default_value' => '',
    );

    // Drupal 7 doesn't automatically give hidden elements an #id.
    $form['eloqua']['elqCustomerGUID']['#attributes']['id'] = 'edit-elqCustomerGUID';
    $form['eloqua']['elqCookieWrite'] = array(
      '#type' => 'hidden',
      '#default_value' => 0,
    );

    // Add GUID tracking
    $form['#attached']['js'][] = drupal_get_path('module', 'eloqua_webform') . '/eloqua_webform.js';

    // Hooks that don't need to load up all the checks to see if said form is
    // eloqua_enabled.
    foreach (module_implements('eloqua_form_alter') as $module_name) {
      $method = $module_name . '_eloqua_form_alter';
      $method($form, $form_state, $form_id);
    }
  }
}

/**
 * Form submission handler for eloqua_admin_form().
 *
 * @see eloqua_webform_form_alter()
 */
function eloqua_webform_submit($form, $form_state) {

  // Only process upon the final page submission, unless otherwise told.
  $process_every_page = $form_state['values']['process_every_page'];
  if (!$process_every_page) {
    if (!array_key_exists('webform_completed', $form_state) || !$form_state['webform_completed']) {
      return;
    }
  }
  $values = array();

  // Collapse form values so they make more sense to Eloqua.
  $post_fields = automate_webform_values($form, $form_state);
  $node = node_load($form_state['values']['details']['nid']);
  $components = $node->webform['components'];
  $field_mappings = array();
  if (is_array($components)) {
    foreach ($components as $component) {
      if (!empty($component['extra']['eloqua']['key'])) {
        $field_mappings[$component['form_key']]['key'] = $component['extra']['eloqua']['key'];
      }
      else {
        $field_mappings[$component['form_key']]['key'] = $component['form_key'];
      }
    }
  }
  $values['form_post'] = automate_map_webform_values($post_fields, $field_mappings);

  // Grab Eloqua hidden values.
  foreach ($form_state['values'] as $name => $value) {
    if (substr($name, 0, 3) === 'elq') {
      $values['form_post'][$name] = $value;
    }
  }

  // Get apache headers.
  $values['user_headers'] = automate_get_user_headers();

  // Save the values and essential information to the database.
  $info = new stdClass();
  $info->{'form_id'} = $form_state['values']['form_id'];
  $info->{'post_time'} = time();
  $info->{'status'} = ELOQUA_STATUS_NEW;
  $info->{'data'} = $values;
  $post = eloqua_post_create($info);

  // Do we want to process immediately?
  if (variable_get('eloqua_webform_process_submit', 0)) {
    _eloqua_send_posts($post);
  }
  if (!isset($post->post_id)) {
    $message = t('Unable to save submitted entry. <pre>!data</pre>');
    $vars = array(
      '!data' => var_export($info, TRUE),
    );
    watchdog('eloqua', $message, $vars, WATCHDOG_NOTICE);
  }
}

/**
 * Maps the URL parameters to the associated form fields.
 *
 * @param array $form
 *   The form.
 * @param array $component_list
 *   The components must be keyed by CID.
 */
function _eloqua_form_url_map(&$form, $component_list) {
  foreach ($component_list as $component) {
    if (empty($component['extra']['eloqua']['query_name'])) {
      continue;
    }

    // Check whether the value is indeed in the query.
    $field_param_name = $component['extra']['eloqua']['query_name'];
    if (!array_key_exists($field_param_name, $_REQUEST)) {
      continue;
    }

    // Determine nesting level.
    $path = array(
      $component['form_key'],
    );
    $current_component = $component;

    // Walk up the path.
    while ($current_component != NULL && $current_component['pid'] != 0) {
      $current_component = $component_list[$current_component['pid']];
      array_unshift($path, $current_component['form_key']);
    }
    $target_element =& $form['submitted'];
    $pass = TRUE;
    foreach ($path as $level) {
      if (array_key_exists($level, $target_element)) {
        $target_element =& $target_element[$level];
      }
      else {
        $pass = FALSE;
        continue;
      }
    }

    // If we found the target form element, update the default value.
    if ($pass) {
      $conversion_method = '_eloqua_form_url_map_' . $component['type'];
      if (function_exists($conversion_method)) {
        $conversion_method($_REQUEST[$field_param_name], $target_element);
      }
      else {
        $target_element['#default_value'] = $_REQUEST[$field_param_name];
      }
    }

    // Release the reference.
    unset($target_element);
  }
}