You are here

eloqua.module in Eloqua 6

Same filename and directory in other branches
  1. 8 eloqua.module
  2. 7.2 eloqua.module
  3. 7 eloqua.module

File

eloqua.module
View source
<?php

/**
 * Eloqua Integraation 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
 */

/**
 * Include support module
 */
module_load_include('inc', 'eloqua');

/**
 * Implementation of hook_init().
 */
function eloqua_init() {
  $directory = variable_get(ELOQUA_VARIABLE_SCRIPTS_DIRECTORY, ELOQUA_VARIABLE_SCRIPTS_DIRECTORY_DEFAULT);

  // Throw an error if either of our 2 primary js files do not exist.
  foreach (array(
    'elqCfg',
    'elqImg',
  ) as $file) {
    if (!file_exists($directory . '/' . $file . '.js')) {
      drupal_set_message(t('You must place the !file.js file in !directory for the eloqua module to function.', array(
        '!file' => $file,
        '!directory' => $directory,
      )), 'error');
    }
    else {
      drupal_add_js($directory . '/' . $file . '.js');
    }
  }
}

/**
 * Implementation of hook_menu().
 */
function eloqua_menu() {
  $items = array();
  $items['admin/settings/eloqua'] = array(
    'title' => 'Eloqua',
    'description' => 'Create and edit Eloqua settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'eloqua_admin_form',
    ),
    'access arguments' => array(
      'access administration pages',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'eloqua.admin.inc',
  );
  return $items;
}
function eloqua_cron() {

  // Load the cron functionality
  module_load_include('inc', 'eloqua', 'eloqua.cron');
  _eloqua_cron();
}

/**
 * Returns the list of exempt component types
 * @return array
 */
function _eloqua_webform_component_get_exempt_types() {
  return array(
    'fieldset',
    'pagebreak',
  );
}

/**
 * Tests whether the given component type is valid for Eloqua Integration
 * @param  $test_type
 * @return bool
 */
function _eloqua_is_valid_component_type($test_type) {
  $invalid_types = _eloqua_webform_component_get_exempt_types();
  $result = in_array($test_type, $invalid_types);
  $result = !$result;
  return $result;
}

/**
 * Implementatation of 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_form_webform_component_edit_form_alter(&$form, $form_state) {
  $component = array_key_exists(3, $form['#parameters']) ? $form['#parameters'][3] : NULL;
  if ($component === NULL) {
    return;
  }

  // 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
  if (!_eloqua_is_valid_component_type($component['type'])) {
    $form['eloqua']['msg'] = array(
      '#type' => 'markup',
      '#value' => t('This component type is not compatible with the Eloqua Module.'),
    );
    return;
  }
  $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_form_webform_component_edit_form_validate';
}

/**
 * Presave handler
 * @param  $component
 * @return void
 */
function eloqua_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
 * @param $form
 * @param $form_state
 * @return unknown_type
 */
function eloqua_form_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 (_).'));
    }
  }
}

/**
 * Implementation of hook_form_FORM_ID_alter().
 */
function eloqua_form_webform_configure_form_alter(&$form, $form_state) {
  $form['#submit'][] = 'eloqua_form_webform_configure_form_submit';
  $form['#validate'][] = 'eloqua_form_webform_configure_form_validate';

  // Load the form options from the database if available
  $settings = new stdClass();
  if (!empty($form['nid']['#value'])) {
    $settings = eloqua_webform_load($form['nid']['#value']);
  }

  // Apply default settings
  if (!isset($settings->{ELOQUA_WEBFORM_FIELD_ACTIVE})) {
    $settings->{ELOQUA_WEBFORM_FIELD_ACTIVE} = 0;
  }
  if (!isset($settings->{ELOQUA_WEBFORM_FIELD_FORM_NAME})) {
    $settings->{ELOQUA_WEBFORM_FIELD_FORM_NAME} = '';
  }
  if (!isset($settings->{ELOQUA_WEBFORM_FIELD_DATA})) {
    $settings->{ELOQUA_WEBFORM_FIELD_DATA} = new stdClass();
  }
  if (!isset($settings->{ELOQUA_WEBFORM_FIELD_DATA}->process_every_page)) {
    $settings->{ELOQUA_WEBFORM_FIELD_DATA}->process_every_page = 0;
  }
  $form['eloqua'] = array(
    '#type' => 'fieldset',
    '#description' => t('Eloqua Integration Options'),
    '#title' => t('Eloqua'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    'elq_enabled' => array(
      '#type' => 'checkbox',
      '#default_value' => $settings->{ELOQUA_WEBFORM_FIELD_ACTIVE},
      '#description' => t('Whether this form is eloqua enabled'),
      '#title' => t('Enabled'),
    ),
    'elq_form_name' => array(
      '#type' => 'textfield',
      '#default_value' => $settings->{ELOQUA_WEBFORM_FIELD_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->{ELOQUA_WEBFORM_FIELD_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 seperately'),
    ),
  );
}

/**
 * Form Validation Function
 * @param $form
 * @param $form_state
 * @return unknown_type
 */
function eloqua_form_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 _'));
    }
  }
}

/**
 * Submit handler for webform_configure_form
 * @param $form array
 * @param $form_state array
 */
function eloqua_form_webform_configure_form_submit($form, &$form_state) {

  // On a new form
  $nid = $form_state['values']['nid'];
  $values = $form_state['values'];
  $webform = new stdClass();
  $webform->{ELOQUA_WEBFORM_FIELD_NODE_ID} = $nid;
  $webform->{ELOQUA_WEBFORM_FIELD_ACTIVE} = $values['elq_enabled'];
  $webform->{ELOQUA_WEBFORM_FIELD_FORM_NAME} = $values['elq_form_name'];
  $webform->{ELOQUA_WEBFORM_FIELD_DATA} = (object) array(
    'process_every_page' => $values['elq_process_every_page'],
  );
  eloqua_webform_create($webform);
}

/**
 * Implementation of hook_form_alter().
 */
function eloqua_form_alter(&$form, $form_state, $form_id) {

  // 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 (!isset($form['details']['nid']['#value']) || empty($form['details']['nid']['#value'])) {
    return;
  }
  $nid = $form['details']['nid']['#value'];
  $form_settings = (array) eloqua_webform_load($nid);

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

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

  // Just shove everything into a container
  $form['#submit'][] = 'eloqua_webform_submit';
  $form['eloqua'] = array();
  $process_every_page = is_object($form_settings[ELOQUA_SETTINGS_FIELD_DATA]) && isset($form_settings[ELOQUA_SETTINGS_FIELD_DATA]->process_every_page) ? $form_settings[ELOQUA_SETTINGS_FIELD_DATA]->process_every_page : FALSE;
  $form['eloqua']['process_every_page'] = array(
    '#type' => 'value',
    '#value' => $process_every_page,
  );
  $form['eloqua']['elqFormName'] = _eloqua_form_hidden($form_settings[ELOQUA_WEBFORM_FIELD_FORM_NAME]);
  $form['eloqua']['elqSiteId'] = _eloqua_form_hidden(eloqua_get_site_id());
  $form['eloqua']['elqDefaultTargetURL'] = _eloqua_form_hidden('');
  $form['eloqua']['elqPost'] = _eloqua_form_hidden('');
  $form['eloqua']['elqCustomerGUID'] = _eloqua_form_hidden('');
  $form['eloqua']['elqCookieWrite'] = _eloqua_form_hidden('0');

  // Add Javascript Init
  $form['eloqua']['script']['setting'] = array(
    '#type' => 'markup',
    '#value' => '<script type="text/javascript" language="JavaScript">var elqPPS="70";</script>',
  );
  $directory = variable_get(ELOQUA_VARIABLE_SCRIPTS_DIRECTORY, ELOQUA_VARIABLE_SCRIPTS_DIRECTORY_DEFAULT);
  $js_file = base_path() . $directory . '/elqScr.js';
  $form['eloqua']['script']['external'] = array(
    '#type' => 'markup',
    '#value' => '<script type="text/javascript" language="JavaScript" src="' . $js_file . '"></script>',
  );
  $initScript = <<<EOJS
<script type="text/javascript" language="JavaScript">
\$(document).ready(function() {
  if (GetElqCustomerGUID) {
    \$('#edit-elqCustomerGUID').val(GetElqCustomerGUID());
  }
});
// </script>
EOJS;
  $form['eloqua']['script']['init'] = array(
    '#type' => 'markup',
    '#value' => $initScript,
  );
  $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
 */
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;
}

/**
 * Submit handler for the webform
 * @param $form array
 * @param $form_state array
 */
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->{ELOQUA_POST_FIELD_FORM_ID} = $form_state['values']['form_id'];
  $info->{ELOQUA_POST_FIELD_POST_TIME} = time();
  $info->{ELOQUA_POST_FIELD_STATUS} = ELOQUA_STATUS_NEW;
  $info->{ELOQUA_POST_FIELD_DATA} = $values;
  $post_id = eloqua_post_create($info);
  if (!$post_id) {
    $message = t('Unable to save submitted entry. <pre>!data</pre>');
    $vars = array(
      '!data' => var_export($info, TRUE),
    );
    watchdog(ELOQUA_WATCHDOG_CATEGORY, $message, $vars, WATCHDOG_NOTICE);
  }
}

/**
 * Convenience Function returning a fAPI compatible hidden field
 * @param $value string
 * @return array
 *  fAPI Form Element
 */
function _eloqua_form_hidden($value) {
  return array(
    '#type' => 'hidden',
    '#default_value' => (string) $value,
  );
}

/**
 * Recursively builds the array tree that will need to be parsed to find values
 * in the post.
 *
 * @param $components - the components array from webform
 * @param $cid - the component id
 * @return array - an array representing tree selections to find a value
 */
function eloqua_get_nesting($components, $cid) {
  if ($components[$cid]['pid'] == 0) {
    return array(
      $components[$cid]['form_key'],
    );
  }
  else {
    return array_merge(eloqua_get_nesting($components, $components[$cid]['pid']), array(
      $components[$cid]['form_key'],
    ));
  }
}

/**
 * Maps the url parameters to the associated form fields
 * @param  $form
 * @param  $component_list
 *   The components must be keyed by cid
 * @return void
 */
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 = _eloqua_form_url_get_component_path($component_list, $component);
    $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);
  }
}

/**
 * Convert URLDate to form date
 * The date must be in yyyy-mm-dd format
 * @param  $value
 * @param  $element
 * @return void
 */
function _eloqua_form_url_map_date($value, &$element) {
  $split = explode('-', $value);

  // Valdiate format
  if (count($split) != 3 || !is_numeric($split[0]) || !is_numeric($split[1]) || !is_numeric($split[2])) {
    return;
  }
  $year = (int) $split[0];
  $month = (int) $split[1];
  $day = (int) $split[2];

  // Valdiate value
  if ($year < 0 || $year > 9999 || !checkdate($month, $day, $year)) {
    return;
  }

  // Update the default value.
  // THe webform #process function expects a keyed array.
  $element['#default_value'] = array(
    'year' => $year,
    'month' => $month,
    'day' => $day,
  );
}

/**
 * Convert url time to form time
 * The time must be a 24 hour format
 * @param  $value
 * @param  $element
 * @return void
 */
function _eloqua_form_url_map_time($value, &$element) {
  $split = explode(':', $value);

  // Validate the format
  if (count($split) != 2 || !is_numeric($split[0]) || !is_numeric($split[1])) {
    return;
  }
  $split[0] = (int) $split[0];
  $split[1] = (int) $split[1];

  // Validate the ranges
  if ($split[0] > 23 || $split[1] > 59 || $split[1] < 0 || $split[0] < 0) {
    return;
  }
  $hour = $split[0];
  $minute = $split[1];

  // If the form is 12-hr, convert
  if (array_key_exists('ampm', $element)) {
    $ampm = $hour >= 12 ? 'pm' : 'am';
    $element['ampm']['#default_value'] = $ampm;
    $hour = $hour > 12 || $hour == 0 ? abs($hour - 12) : $hour;
  }
  $element['hour']['#default_value'] = $hour;
  $element['minute']['#default_value'] = $minute;
}

/**
 * Returns the nesting keys for a component
 * @param  $component_list
 * @param  $target_component
 * @return array
 */
function _eloqua_form_url_get_component_path($component_list, $target_component) {
  $path = array(
    $target_component['form_key'],
  );
  $current_component = $target_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']);
  }
  return $path;
}

// END OF FILE

Functions

Namesort descending Description
eloqua_cron
eloqua_form_alter Implementation of hook_form_alter().
eloqua_form_webform_component_edit_form_alter Implementatation of 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.
eloqua_form_webform_component_edit_form_validate Validates the eloqua field @todo Make this less Western Centric. Get parameters should be able to accept all Unicode code-points
eloqua_form_webform_configure_form_alter Implementation of hook_form_FORM_ID_alter().
eloqua_form_webform_configure_form_submit Submit handler for webform_configure_form
eloqua_form_webform_configure_form_validate Form Validation Function
eloqua_get_nesting Recursively builds the array tree that will need to be parsed to find values in the post.
eloqua_init Implementation of hook_init().
eloqua_menu Implementation of hook_menu().
eloqua_webform_component_presave Presave handler
eloqua_webform_submit Submit handler for the webform
_eloqua_form_hidden Convenience Function returning a fAPI compatible hidden field
_eloqua_form_url_get_component_path Returns the nesting keys for a component
_eloqua_form_url_map Maps the url parameters to the associated form fields
_eloqua_form_url_map_date Convert URLDate to form date The date must be in yyyy-mm-dd format
_eloqua_form_url_map_time Convert url time to form time The time must be a 24 hour format
_eloqua_is_valid_component_type Tests whether the given component type is valid for Eloqua Integration
_eloqua_webform_component_get_exempt_types Returns the list of exempt component types
_eloqua_webform_get_user_headers Returns the user headers filtered for types that shouldn't be needed This function currently is Apache module specific