You are here

eloqua_webform.module in Eloqua 7

Same filename and directory in other branches
  1. 7.2 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_cron();
}

/**
 * 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);
    if (is_null($settings)) {
      $settings = new stdClass();
    }
  }

  // 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', ''),
      ),
    );
  }

  // We only want to edit client versions of the webform. If it's anything else
  // simply return.
  if (strpos($form_id, 'webform_client_form') !== 0) {
    return;
  }
  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';
  $user_headers = _eloqua_webform_get_user_headers();
  $form['eloqua']['user_headers'] = array(
    '#type' => 'hidden',
    '#default_value' => serialize($user_headers),
  );

  // 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);
  }
}

/**
 * Returns the user headers filtered for types that shouldn't be needed.
 *
 * This function currently is Apache module specific.
 *
 * @return array
 *   The user headers.
 */
function _eloqua_webform_get_user_headers() {

  // Getting the request headers only exists in Apache.
  if (!function_exists('apache_request_headers')) {
    return array();
  }
  $headers = apache_request_headers();

  // Check to see if the function succeeded or not.
  if (!$headers) {
    return array();
  }
  $filter = array(
    'host',
    'cookie',
  );
  $result = array();
  foreach ($headers as $key => $value) {
    if (!in_array(strtolower($key), $filter)) {
      $result[strtolower($key)] = $value;
    }
  }
  return $result;
}

/**
 * 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();
  $values['form_post'] = $form_state['values'];
  $values['user_headers'] = unserialize($form_state['values']['user_headers']);

  // Check for serialization errors.
  if ($values['user_headers'] == FALSE) {
    $values['user_headers'] = array();
  }
  unset($values['form_post']['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_cron($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);
  }
}

Functions

Namesort descending Description
eloqua_webform_component_edit_form_validate Validates the Eloqua field.
eloqua_webform_configure_form Eloqua webform configure form.
eloqua_webform_configure_form_submit Form submission handler for eloqua_webform_configure_form().
eloqua_webform_configure_form_validate Form validation handler for eloqua_webform_configure_form().
eloqua_webform_cron Implements hook_cron().
eloqua_webform_form_alter Implements hook_form_alter().
eloqua_webform_form_webform_component_edit_form_alter Implements hook_form_FORM_ID_alter().
eloqua_webform_menu Implements hook_menu().
eloqua_webform_submit Form submission handler for eloqua_admin_form().
eloqua_webform_webform_component_presave Implements hook_webform_component_presave().
_eloqua_form_url_map Maps the URL parameters to the associated form fields.
_eloqua_webform_get_user_headers Returns the user headers filtered for types that shouldn't be needed.