You are here

uc_webform.module in Ubercart Webform Integration 6

Same filename and directory in other branches
  1. 7.3 uc_webform.module
  2. 7 uc_webform.module
  3. 7.2 uc_webform.module

Provides components to the Webform module utilizing the Ubercart package.

File

uc_webform.module
View source
<?php

/**
 * @file
 * Provides components to the Webform module utilizing the Ubercart package.
 */

/**
 * Implementation of hook_menu().
 */
function uc_webform_menu() {
  $items = array();
  $items['cart/delete-form'] = array(
    'title' => 'Delete',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'uc_webform_submission_delete_products_form',
    ),
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['uc_webform/autocomplete'] = array(
    'title' => 'Product autocomplete',
    'page callback' => '_uc_webform_autocomplete_products',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['node/%webform_menu/webform-results/orders'] = array(
    'title' => 'Orders',
    'page callback' => 'uc_webform_product_analysis',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'webform_results_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 5,
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
 * Implementation of hook_theme().
 */
function uc_webform_theme() {
  return array(
    'uc_webform_product_analysis' => array(
      'arguments' => array(
        'node' => NULL,
      ),
    ),
  );
}

/**
 * Provides an auto-complete list of products that do not contain attributes.
 */
function _uc_webform_autocomplete_products($string = '') {
  $matches = array();

  // Limit selection to only those products that do *not* contain attributes.
  $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, p.model FROM {node} AS n INNER JOIN {uc_products} AS p ON n.nid = p.nid WHERE n.title LIKE '%%%s%' AND n.nid NOT IN (SELECT nid FROM {uc_product_attributes}) AND n.status = 1"), $string, 0, 10);
  while ($product = db_fetch_object($result)) {
    $matches[$product->nid . '_' . check_plain($product->model)] = check_plain($product->title);
  }
  drupal_json($matches);
}

/**
 * Provides a simple analysis of submissions that contain products.
 *
 * Called when viewing the "Orders" tab from within the results section of a
 * particular webform.
 */
function uc_webform_product_analysis($node, $sids = array(), $analysis_component = NULL) {
  if (!is_array($sids)) {
    $sids = array();
  }

  // If showing a component's details, we don't want to loose the menu tabs.
  if ($analysis_component) {
    $item = menu_get_item('node/' . $node->nid . '/webform-results/analysis');
    menu_set_item(NULL, $item);
  }
  $components = isset($analysis_component) ? array(
    $analysis_component['cid'] => $analysis_component,
  ) : $node->webform['components'];
  $data = array();
  $cids = array();
  $order_status_cid = 0;

  // First, find the Order Status cid.
  foreach ($components as $cid => $component) {
    if ($component['form_key'] == 'order_status') {
      $order_status_cid = $component['cid'];
      break;
    }
  }
  foreach ($components as $cid => $component) {

    // Limit the results to product, hidden_product and product_list components.
    if ($component['type'] == 'product' || $component['type'] == 'hidden_product') {
      if ($row_data = _uc_webform_product_orders($component, $order_status_cid)) {
        $data[$cid] = $row_data;
      }
      $cids[] = $component['cid'];
    }
    elseif ($component['type'] == 'product_list') {
      if ($row_data = _uc_webform_product_list_orders($component, $order_status_cid)) {
        $data[$cid] = $row_data;
      }
      $cids[] = $component['cid'];
    }
    elseif ($component['type'] == 'product_grid') {
      if ($row_data = _uc_webform_product_grid_orders($component, $order_status_cid)) {
        $data[$cid] = $row_data;
      }
      $cids[] = $component['cid'];
    }
  }
  if (empty($cids)) {
    return t('There are no products associated with this webform.');
  }
  else {
    return theme('uc_webform_product_analysis', $node, $data, $sids, $analysis_component, $order_status_cid);
  }
}

/**
 * Generate statistics for product components, limited to checked out webforms.
 *
 * This information is displayed under the "orders" tab of the webform results.
 */
function _uc_webform_product_orders($component, $order_status_cid) {

  // First, get the list of all submission IDs for webform submissions where
  // checkout has been completed.
  $checked_out_sids = db_query("SELECT sid FROM {webform_submitted_data} WHERE nid = %d AND cid = %d AND data <> 'Did not complete checkout'", $component['nid'], $order_status_cid);
  $sids = array();
  while ($submission = db_fetch_array($checked_out_sids)) {
    $sids[] = $submission['sid'];
  }

  // Skip the rest if no sids were found.
  if (empty($sids)) {
    return array();
  }

  // Use the array of checked out submission ID's to grab only the checked out
  // product data.
  $placeholders = db_placeholders($sids);
  $arguments = array_merge(array(
    $component['cid'],
    $component['nid'],
  ), $sids);
  $co_results = db_query("SELECT * FROM {webform_submitted_data} WHERE cid = %d AND nid = %d AND sid IN ({$placeholders})", $arguments);
  $total = 0;
  while ($co_result = db_fetch_array($co_results)) {
    if ($co_result['no'] == 2) {
      $total += $co_result['data'];
    }
  }
  $product_info = explode('_', $component['extra'][$component['type']], 2);
  $rows[0] = array(
    t($product_info[1]),
    $total,
  );
  if ($total > 0) {
    return $rows;
  }
  else {
    return NULL;
  }
}

/**
 * Statistics for product_list components, limited to checked out webforms.
 *
 * This information is displayed under the "Orders" tab of the webform results.
 */
function _uc_webform_product_list_orders($component, $order_status_cid) {

  // First, get the list of all submission IDs for webform submissions where
  // checkout has been completed.
  $checked_out_sids = db_query("SELECT sid FROM {webform_submitted_data} WHERE nid = %d AND cid = %d AND data <> 'Did not complete checkout'", $component['nid'], $order_status_cid);
  $sids = array();
  while ($submission = db_fetch_array($checked_out_sids)) {
    $sids[] = $submission['sid'];
  }

  // Use the array of checked out submission ID's to grab only the checked out
  // product data.
  $placeholders = db_placeholders($sids);
  $arguments = array_merge(array(
    $component['cid'],
    $component['nid'],
  ), $sids);
  $co_results = db_query("SELECT * FROM {webform_submitted_data} WHERE cid = %d AND nid = %d AND sid IN ({$placeholders})", $arguments);
  $product_results = array();
  while ($co_result = db_fetch_array($co_results)) {
    if ($co_result['no'] == 0) {
      continue;
    }
    else {
      if (array_key_exists($co_result['data'], $product_results)) {
        $product_results[$co_result['data']] += 1;
      }
      else {
        $product_results[$co_result['data']] = 1;
      }
    }
  }
  $rows = array();
  $count = 0;
  foreach ($product_results as $product => $qty) {
    $product_info = explode('_', $product, 2);
    $product_node = node_load($product_info[0]);
    $rows[$count] = array(
      check_plain($product_node->model),
      $qty,
    );
    $count++;
  }
  return $rows;
}

/**
 * Generate statistics for product_grid components, limited to checked out webforms.
 * This information is displayed under the "orders" tab of the webform results.
 *
 */
function _uc_webform_product_grid_orders($component, $order_status_cid) {

  // Build the rows of the table, including the first column.
  $rows = array(
    array(),
  );
  $header = array(
    array(),
  );
  $product_nids = array();
  foreach ($component['extra']['products'] as $product) {
    $nid_sku = explode('_', $product, 2);
    $product_nids[] = $nid_sku[0];
    $product_node = node_load($nid_sku[0]);

    // I use the nid_sku combination here as a key
    $rows[$product] = array(
      check_plain($product_node->title),
    );
  }

  // Select the available option IDs and names for each product in the table.
  $placeholders = db_placeholders($product_nids);
  $result = db_query("SELECT DISTINCT po.oid, ao.name FROM {uc_product_options} AS po INNER JOIN {uc_attribute_options} AS ao ON po.oid = ao.oid WHERE po.nid IN ({$placeholders})", $product_nids);

  // Build the header row.
  $options = array();
  while ($option = db_fetch_array($result)) {

    // Use the oid as an array key to help when quering the
    // webform_submitted_data table (since it stores the oid instead of the
    // option name).
    $header[$option['oid']] = check_plain($option['name']);
  }

  // Get a list of all submission IDs for submissions with completed checkouts.
  $checked_out_sids = db_query("SELECT sid FROM {webform_submitted_data} WHERE nid = %d AND cid = %d AND data <> 'Did not complete checkout'", $component['nid'], $order_status_cid);
  $sids = array();
  while ($submission = db_fetch_array($checked_out_sids)) {
    $sids[] = $submission['sid'];
  }

  // Use the array of checked out submission ID's to grab only the checked out
  // product data.
  $placeholders = db_placeholders($sids);
  $arguments = array_merge(array(
    $component['cid'],
    $component['nid'],
  ), $sids);
  $co_results = db_query("SELECT no, data, count(data) AS datacount FROM {webform_submitted_data} WHERE cid = %d AND nid = %d AND sid IN ({$placeholders}) GROUP BY no, data", $arguments);
  $selections = array();
  while ($data = db_fetch_array($co_results)) {
    $aid_oid = explode('_', $data['data'], 2);

    // The information is stored in the DB as attribute-ID_option-ID. This line
    // removes the attribute ID and leaves the $selections key as the option ID.
    $selections[$data['no']][$aid_oid[1]] = $data['datacount'];
  }

  // Check to see if any completed orders include this component. Return NULL
  // if there aren't any.
  if (!empty($selections)) {

    // Build up the 2D array that will be used to create the table.
    foreach ($rows as $rkey => $rval) {
      if ($rkey != 0) {
        foreach ($header as $hkey => $hval) {
          if ($hkey != 0) {

            // $rkey = nid_sku
            // $hkey = option ID
            $rows[$rkey][] = isset($selections[$rkey][$hkey]) ? $selections[$rkey][$hkey] : 0;
          }
        }
      }
    }
    $output = theme('table', $header, $rows, array(
      'class' => 'webform-product-grid',
    ));
    return array(
      array(
        array(
          'data' => $output,
          'colspan' => 2,
        ),
      ),
    );
  }
  else {
    return NULL;
  }
}

/**
 * Output the content of the Analysis page.
 *
 * @see webform_results_analysis()
 */
function theme_uc_webform_product_analysis($node, $data, $sids = array(), $analysis_component = NULL, $order_status_cid) {
  $rows = array();
  $question_number = 0;
  $single = isset($analysis_component);
  $header = array(
    $single ? check_plain($analysis_component['name']) : t('Q'),
    array(
      'data' => $single ? '&nbsp' : t('Product Selection (completed checkouts)'),
      'colspan' => '10',
    ),
  );
  foreach ($data as $cid => $row_data) {
    $question_number++;
    if (is_array($row_data)) {
      $row = array();
      if (!$single) {
        $row[] = array(
          'data' => '<strong>' . $question_number . '</strong>',
          'rowspan' => count($row_data) + 1,
          'valign' => 'top',
        );
        $row[] = array(
          'data' => '<strong>' . check_plain($node->webform['components'][$cid]['name']) . '</strong>',
          'colspan' => '10',
        );
      }
      $rows = array_merge($rows, array_merge(array(
        $row,
      ), $row_data));
    }
  }
  $num_no_checkout = db_result(db_query("SELECT COUNT(*) FROM {webform_submitted_data} WHERE nid = %d AND data = 'Did not complete checkout'", $node->nid));
  $total_submissions = db_result(db_query("SELECT COUNT(DISTINCT sid) FROM {webform_submitted_data} WHERE nid = %d", $node->nid));
  $rows[] = array(
    array(
      'data' => '<strong>$</strong>',
      'rowspan' => 4,
      'valign' => 'top',
    ),
    array(
      'data' => '<strong>Checkout statistics</strong>',
      'colspan' => 10,
    ),
  );
  $rows[] = array(
    t('Total completed checkouts'),
    $total_submissions - $num_no_checkout,
  );
  $rows[] = array(
    '<strong>' . t('Total webform submissions') . '</strong>',
    $total_submissions,
  );
  return theme('table', $header, $rows);
}

/**
 * Confirmation form before deleting products from a cart.
 *
 * When removing a single product from a cart alert the user that doing so will
 * also remove all other products associated with the same form.
 */
function uc_webform_submission_delete_products_form() {
  $question = t('If you remove this product from your cart, all products associated with your registration submission will also be removed.  Are you sure you want to delete this product?');
  $destination = 'cart';
  return confirm_form(array(), NULL, $destination, $question, t('Delete'), t('Cancel'));
}
function uc_webform_submission_delete_products_form_submit($form, &$form_state) {

  // Remove all items from the current webform submission from the cart.
  $cart_items = uc_cart_get_contents();
  foreach ($cart_items as $cart_item) {
    if (isset($cart_item->data['webform_sid'])) {
      uc_cart_remove_item($cart_item->nid, $cart_item->cart_id, $cart_item->data);
    }
  }
  $form_state['redirect'] = 'cart';
}

/**
 * Implementation of hook_form_FORM_ID_alter().
 */
function uc_webform_form_uc_cart_view_form_alter(&$form, &$form_state) {
  $count = 0;
  while (isset($form['items'][$count])) {
    if (isset($form['items'][$count]['data']['#value'])) {
      $data = unserialize($form['items'][$count]['data']['#value']);
      if (in_array($data['webform_ctype'], array(
        'product_list',
        'product',
        'hidden_product',
        'product_grid',
      ))) {

        // Check to see if the product was a mandatory field in the webform
        // submission.
        $component_info = db_fetch_array(db_query("SELECT mandatory, extra FROM {webform_component} WHERE nid = %d AND cid = %d", $data['webform_nid'], $data['webform_cid']));
        $component_info['extra'] = unserialize($component_info['extra']);

        // Users may not edit the quantity of a product from the cart.
        $form['items'][$count]['qty']['#disabled'] = TRUE;
        $form['items'][$count]['qty']['#value'] = db_result(db_query("SELECT data FROM {webform_submitted_data} WHERE nid = %d AND sid = %d AND cid = %d AND no = 2", $data['webform_nid'], $data['webform_sid'], $data['webform_cid']));

        // Force the user to remove *all* webform-related products from the
        // cart if they want to remove *one* mandatory webform-related
        // product from the cart.
        if ($component_info['mandatory'] == 1) {
          $form['items'][$count]['remove']['#type'] = 'markup';
          $form['items'][$count]['remove']['#value'] = l(t('Delete'), "cart/delete-form", array(
            'query' => drupal_get_destination(),
          ));
        }
        if ($data['webform_ctype'] == 'product_list' || $data['webform_ctype'] == 'product_grid') {

          // Users may not edit the quantity of a product_list or product_grid webform
          // product.
          $form['items'][$count]['qty']['#disabled'] = TRUE;

          // If #value is not specified here, all products will be removed
          // if any product is removed.
          $form['items'][$count]['qty']['#value'] = 1;
        }
      }
    }
    $count++;
  }
}

/** TAKEN OUT 5/17/2013 BECAUSE IT CLEARS ORDER STATUS HIDDEN FIELD WHEN WEBFORM IS EDITED.
function uc_webform_form_alter(&$form, &$form_state, $form_id) {

  // Ensure that the order_status field cannot be modified with firebug, etc.
  if (isset($form['submitted']['order_status'])) {
    $form['submitted']['order_status']['#value'] = $form['submitted']['order_status']['#default_value'];
    unset($form['submitted']['order_status']['#default_value']);
  }
}
*/

/**
 * Implementation of hook_theme_registry_alter().
 *
 * There is a good article about this here:
 * http://www.lullabot.com/articles/overriding-theme-functions-in-modules
 */
function uc_webform_theme_registry_alter(&$theme_registry) {
  if (!empty($theme_registry['webform_components_form'])) {
    $theme_registry['webform_components_form']['function'] = 'uc_webform_webform_components_form';
  }
}

/**
 * Override 'theme_webform_components_form($form)', found in webform.components.inc.
 * This function will need to be updated everytime quicksketch makes a corresponding change.
 *
 * Remove the 'Clone', 'Edit' and 'Delete' links from the hidden Order Status component if
 * there are products included in the webform.
 */
function uc_webform_webform_components_form($form) {

  // Add CSS to display submission info. Don't preprocess because this CSS file is used rarely.
  drupal_add_css(drupal_get_path('module', 'webform') . '/css/webform-admin.css', 'theme', 'all', FALSE);
  drupal_add_js(drupal_get_path('module', 'webform') . '/js/webform-admin.js', 'module', 'header', FALSE, TRUE, FALSE);
  drupal_add_tabledrag('webform-components', 'order', 'sibling', 'webform-weight');
  drupal_add_tabledrag('webform-components', 'match', 'parent', 'webform-pid', 'webform-pid', 'webform-cid');
  $node = $form['#node'];
  $header = array(
    t('Name'),
    t('Type'),
    t('Value'),
    t('Mandatory'),
    t('Weight'),
    array(
      'data' => t('Operations'),
      'colspan' => 3,
    ),
  );
  $rows = array();

  // Add a row containing form elements for a new item.
  unset($form['add']['name']['#title'], $form['add_type']['#description']);
  $form['add']['name']['#attributes']['rel'] = t('New component name');
  $form['add']['name']['#attributes']['class'] = 'webform-default-value';
  $form['add']['cid']['#attributes']['class'] = 'webform-cid';
  $form['add']['pid']['#attributes']['class'] = 'webform-pid';
  $form['add']['weight']['#attributes']['class'] = 'webform-weight';
  $row_data = array(
    drupal_render($form['add']['name']),
    drupal_render($form['add']['type']),
    '',
    drupal_render($form['add']['mandatory']),
    drupal_render($form['add']['cid']) . drupal_render($form['add']['pid']) . drupal_render($form['add']['weight']),
    array(
      'colspan' => 3,
      'data' => drupal_render($form['add']['add']),
    ),
  );
  $add_form = array(
    'data' => $row_data,
    'class' => 'draggable webform-add-form',
  );
  $form_rendered = FALSE;
  if (!empty($node->webform['components'])) {
    $component_tree = array();
    $page_count = 1;
    _webform_components_tree_build($node->webform['components'], $component_tree, 0, $page_count);
    $component_tree = _webform_components_tree_sort($component_tree);

    // Build the table rows.
    function _webform_components_form_rows($node, $cid, $component, $level, &$form, &$rows, &$add_form) {

      // Create presentable values.
      if (drupal_strlen($component['value']) > 30) {
        $component['value'] = drupal_substr($component['value'], 0, 30);
        $component['value'] .= '...';
      }
      $component['value'] = check_plain($component['value']);

      // Remove individual titles from the mandatory and weight fields.
      unset($form['components'][$cid]['mandatory']['#title']);
      unset($form['components'][$cid]['pid']['#title']);
      unset($form['components'][$cid]['weight']['#title']);

      // Add special classes for weight and parent fields.
      $form['components'][$cid]['cid']['#attributes']['class'] = 'webform-cid';
      $form['components'][$cid]['pid']['#attributes']['class'] = 'webform-pid';
      $form['components'][$cid]['weight']['#attributes']['class'] = 'webform-weight';

      // Build indentation for this row.
      $indents = '';
      for ($n = 1; $n <= $level; $n++) {
        $indents .= '<div class="indentation">&nbsp;</div>';
      }

      // Add each component to a table row.
      // Alteration: I've added this check to remove the 'Edit', 'Clone', 'Delete' links when necessary.
      $product_form = 0;
      foreach ($form['#node']->webform['components'] as $comp) {
        if ($product_form = in_array($comp['type'], array(
          'product',
          'hidden_product',
          'product_list',
          'product_grid',
        ))) {
          break;
        }
      }
      if ($product_form && $component['form_key'] == 'order_status') {

        // Remove the Edit, Clone and Delete links
        $row_data = array(
          $indents . filter_xss($component['name']),
          t($component['type']),
          $component['value'] == '' ? '-' : $component['value'],
          drupal_render($form['components'][$cid]['mandatory']),
          drupal_render($form['components'][$cid]['cid']) . drupal_render($form['components'][$cid]['pid']) . drupal_render($form['components'][$cid]['weight']),
          '-',
          '-',
          '-',
        );
      }
      else {

        // Here is the original code
        $row_data = array(
          $indents . filter_xss($component['name']),
          t($component['type']),
          $component['value'] == '' ? '-' : $component['value'],
          drupal_render($form['components'][$cid]['mandatory']),
          drupal_render($form['components'][$cid]['cid']) . drupal_render($form['components'][$cid]['pid']) . drupal_render($form['components'][$cid]['weight']),
          l(t('Edit'), 'node/' . $node->nid . '/webform/components/' . $cid, array(
            'query' => drupal_get_destination(),
          )),
          l(t('Clone'), 'node/' . $node->nid . '/webform/components/' . $cid . '/clone', array(
            'query' => drupal_get_destination(),
          )),
          l(t('Delete'), 'node/' . $node->nid . '/webform/components/' . $cid . '/delete', array(
            'query' => drupal_get_destination(),
          )),
        );
      }
      $row_class = 'draggable';
      if (!webform_component_feature($component['type'], 'group')) {
        $row_class .= ' tabledrag-leaf';
      }
      if ($component['type'] == 'pagebreak') {
        $row_class .= ' tabledrag-root webform-pagebreak';
        $row_data[0] = array(
          'class' => 'webform-pagebreak',
          'data' => $row_data[0],
        );
      }
      $rows[] = array(
        'data' => $row_data,
        'class' => $row_class,
      );
      if (isset($component['children']) && is_array($component['children'])) {
        foreach ($component['children'] as $cid => $component) {
          _webform_components_form_rows($node, $cid, $component, $level + 1, $form, $rows, $add_form);
        }
      }

      // Add the add form if this was the last edited component.
      if (isset($_GET['cid']) && $component['cid'] == $_GET['cid'] && $add_form) {
        $add_form['data'][0] = $indents . $add_form['data'][0];
        $rows[] = $add_form;
        $add_form = FALSE;
      }
    }
    foreach ($component_tree['children'] as $cid => $component) {
      _webform_components_form_rows($node, $cid, $component, 0, $form, $rows, $add_form);
    }
  }
  else {
    $rows[] = array(
      array(
        'data' => t('No Components, add a component below.'),
        'colspan' => 9,
      ),
    );
  }

  // Append the add form if not already printed.
  if ($add_form) {
    $rows[] = $add_form;
  }
  $output = '';
  $output .= theme('table', $header, $rows, array(
    'id' => 'webform-components',
  ));
  $output .= drupal_render($form);
  return $output;
}

/**
 * Implementation of hook_order().
 */
function uc_webform_order($op, &$arg1, $arg2) {
  switch ($op) {
    case 'submit':
      foreach ($arg1->products as $product) {
        if (isset($product->data['webform_sid'])) {
          if (is_numeric($product->data['webform_nid'])) {
            $node = node_load($product->data['webform_nid']);
            if (isset($node->title)) {
              $title = filter_xss($node->title);
            }
          }
          if ($title == '') {
            $message = l(t('View form submission @!sid', array(
              '@sid' => $product->data['webform_sid'],
            )), 'node/' . $product->data['webform_nid'] . '/submission/' . $product->data['webform_sid']);
          }
          else {
            $message = l(t('View form submission #@sid: @title', array(
              '@sid' => $product->data['webform_sid'],
              '@title' => $title,
            )), 'node/' . $product->data['webform_nid'] . '/submission/' . $product->data['webform_sid']);
          }

          // Add an admin comment that links to the webform submission.
          uc_order_comment_save($arg1->order_id, $arg1->uid, $message, 'admin');
        }
      }
      break;
    case 'update':
      foreach ($arg1->products as $product) {
        if (isset($product->data['webform_sid'])) {

          // Update the hidden Order Status field of the webform submission.
          $status = t('Order #') . $arg1->order_id . ': ' . drupal_strtoupper($arg2);
          $webform_node = node_load($product->data['webform_nid']);
          $webform_submission = webform_menu_submission_load($product->data['webform_sid'], $product->data['webform_nid']);
          if (count($webform_node->webform['components']) && $webform_submission) {
            foreach ($webform_node->webform['components'] as $component) {
              if ($component['form_key'] == 'order_status') {
                $webform_submission->data[$component['cid']]['value'][0] = $status;
                webform_submission_update($webform_node, $webform_submission);
              }
            }
          }
        }
      }
      break;
  }
}

/**
 * Implementation of hook_cart_item().
 */
function uc_webform_cart_item($op, &$item) {
  switch ($op) {
    case 'remove':
      $data = unserialize($item->data);
      if ($data['webform_ctype'] == 'product_list') {
        db_query("DELETE FROM {webform_submitted_data} WHERE nid = %d AND sid = %d AND data = '%s'", $data['webform_nid'], $data['webform_sid'], $item->nid);
      }
      elseif ($data['webform_ctype'] == 'product') {
        db_query("DELETE FROM {webform_submitted_data} WHERE nid = %d AND sid = %d AND cid = %d", $data['webform_nid'], $data['webform_sid'], $data['webform_cid']);
      }
      elseif ($data['webform_ctype'] == 'product_grid') {
        db_query("DELETE FROM {webform_submitted_data} WHERE nid = %d AND sid = %d AND cid = %d", $data['webform_nid'], $data['webform_sid'], $data['webform_cid']);
      }
      break;
  }
}

/**
 * Implementation of hook_webform_component_info().
 *
 * Define components available to Webform.
 *
 * @see http://drupal.org/node/886014
 */
function uc_webform_webform_component_info() {
  return array(
    'product_list' => array(
      'label' => t('Product list'),
      'description' => t('Add a list of products to your webform.'),
      'features' => array(
        'csv' => TRUE,
        'email' => TRUE,
        'required' => TRUE,
      ),
      'file' => 'components/product_list.inc',
    ),
    'product' => array(
      'label' => t('Product'),
      'description' => t('Add a single product to your webform.'),
      'features' => array(
        'csv' => TRUE,
        'email' => TRUE,
        'required' => TRUE,
      ),
      'file' => 'components/product.inc',
    ),
    'product_grid' => array(
      'label' => t('Product grid'),
      'description' => t('Add a grid of products that contain attributes. Users select options.'),
      'features' => array(
        'csv' => TRUE,
        'email' => TRUE,
        'required' => TRUE,
      ),
      'file' => 'components/product_grid.inc',
    ),
    'hidden_product' => array(
      'label' => t('Hidden product'),
      'description' => t('A product which is not visible to the user, but which will be added to the cart with the webform submission.'),
      'file' => 'components/hidden_product.inc',
      'features' => array(
        'required' => FALSE,
        'email_address' => TRUE,
        'email_name' => TRUE,
        'title_display' => FALSE,
      ),
    ),
  );
}

/**
 * Respond to a Webform submission being inserted.
 */
function uc_webform_webform_submission_insert($node, $submission) {

  // NOTE: commented out code that prevented submitting same form multiple times.
  // Let's say user wants to buy webform for himself and same one for a friend.
  // In previous version it d=couldn't do it. Now it can
  // TODO: remove commented out code later to clean up file.
  // If the latest webform submission has products in it, remove the
  // previous webform submission products and add the new ones. Otherwise,
  // allow the form to be submitted without incident.
  //   foreach ($node->webform['components'] as $component) {
  //     if (($component['type'] == 'product_list') || ($component['type'] == 'product') || ($component['type'] == 'product_grid') || ($component['type'] == 'hidden_product')) {
  //       $remove = TRUE;
  //       break;
  //     }
  //   }
  $remove_sid = FALSE;

  //   if ($remove) {
  // Remove items from previous webform submissions from the cart.
  //     $cart_items = uc_cart_get_contents();
  //
  //     foreach ($cart_items as $cart_item) {
  //       if (isset($cart_item->data['webform_sid']) && ($cart_item->data['webform_sid'] != $submission->sid)) {
  //         // Capture the submission ID of the previous submission so that we can
  //         // clean up the webform tables next.
  //         $remove_sid = (integer) $cart_item->data['webform_sid'];
  //
  //         // Remove the item from the cart.
  //         uc_cart_remove_item($cart_item->nid, $cart_item->cart_id, $cart_item->data);
  //       }
  //     }
  //
  //     if ($remove_sid) {
  //       // Remove the previous submissions from the webform tables.
  //       db_query("DELETE FROM {webform_submitted_data} WHERE sid = %d", $remove_sid);
  //       db_query("DELETE FROM {webform_submissions} WHERE sid = %d", $remove_sid);
  //     }
  // Add new items to the cart.
  foreach ($node->webform['components'] as $component) {
    if ($component['type'] == 'product_list') {
      if (array_key_exists($component['cid'], $submission->data)) {
        $key = $component['cid'];
        foreach ($submission->data[$key]['value'] as $val) {

          // This is all very dependent on the way that the product data is
          // stored in the webform_submitted_data table. Take a look there,
          // and also check out the uc_webform README.txt file.
          $product_info = explode('_', $val, 2);
          if (is_numeric($product_info[0])) {
            uc_cart_add_item($product_info[0], 1, array(
              'webform_sid' => $submission->sid,
              'webform_nid' => $node->nid,
              'webform_ctype' => 'product_list',
              'webform_cid' => $component['cid'],
            ));
          }
        }
      }
    }
    elseif ($component['type'] == 'product' || $component['type'] == 'hidden_product') {
      if (array_key_exists($component['cid'], $submission->data)) {
        $key = $component['cid'];

        // The quantity specified by the user.
        $qty = (int) $submission->data[$key]['value'][2];
        $component_data = unserialize(db_result(db_query('SELECT extra FROM {webform_component} WHERE cid = %d AND nid = %d', $component['cid'], $node->nid)));

        // $product_info will contain an array with the product node ID and
        // the selected model (sku).
        $product_info = explode('_', $component_data[$component['type']], 2);
        if ($qty > 0) {
          uc_cart_add_item($product_info[0], $qty, array(
            'webform_sid' => $submission->sid,
            'webform_nid' => $node->nid,
            'webform_ctype' => $component['type'],
            'webform_cid' => $component['cid'],
          ));
        }
      }
    }
    elseif ($component['type'] == 'product_grid') {
      if (array_key_exists($component['cid'], $submission->data)) {
        $cid = $component['cid'];
        foreach ($submission->data[$cid]['value'] as $key => $prod_option) {

          // This is all very dependent on the way that the product data is
          // stored in the webform_submitted_data table. Take a look there,
          // and also check out the uc_webform README.txt file.
          if ($prod_option) {
            $product_info = explode('_', $key, 2);

            // The $prod_option variable actually contains both the attribute
            // ID and the option ID in the form of a string: aid_oid.
            $option_info = explode('_', $prod_option, 2);
            uc_cart_add_item($product_info[0], 1, array(
              'attributes' => array(
                $option_info[0] => $option_info[1],
              ),
              'webform_sid' => $submission->sid,
              'webform_nid' => $node->nid,
              'webform_ctype' => 'product_grid',
              'webform_cid' => $component['cid'],
            ));
          }
        }
      }
    }
  }

  //   }
}

/**
 * Implementation of hook_webform_component_insert().
 *
 * Respond to a Webform component being inserted into the database.
 */
function uc_webform_webform_component_insert($component) {
  if ($component['type'] == 'product' || $component['type'] == 'product_list' || $component['type'] == 'product_grid' || $component['type'] == 'hidden_product') {

    // Check to see whether the hidden field already exists.
    $result = db_result(db_query("SELECT cid FROM {webform_component} WHERE nid = %d AND form_key = 'order_status'", $component['nid']));
    $extra = array(
      'conditional_operator' => '=',
    );
    if (!$result) {

      // Insert a hidden field into the webform.
      $order_status_component = array(
        nid => $component['nid'],
        form_key => 'order_status',
        name => 'Order Status',
        type => 'hidden',
        value => 'Did not complete checkout',
        extra => $extra,
        mandatory => 0,
        weight => 100,
      );
      webform_component_insert($order_status_component);
    }
  }
}

/**
 * Respond to a Webform component being updated in the database.
 */
function uc_webform_webform_component_update($component) {
  if ($component['type'] == 'product' || $component['type'] == 'product_list' || $component['type'] == 'product_grid' || $component['type'] == 'hidden_product') {

    // We need to check to see whether the hidden field already exists.
    // We also need to find the max component id in the webform.
    $results = db_query("SELECT cid, form_key FROM {webform_component} WHERE nid = %d", $component['nid']);
    $components_info['cids'] = array();
    $components_info['form_keys'] = array();
    while ($result = db_fetch_array($results)) {
      array_push($components_info['cids'], $result['cid']);
      array_push($components_info['form_keys'], $result['form_key']);
    }
    $extra = array(
      'conditional_operator' => '=',
    );
    if (!in_array('order_status', $components_info['form_keys'])) {

      // Insert a hidden field into the webform.
      $order_status_component = array(
        nid => $component['nid'],
        form_key => 'order_status',
        name => 'Order Status',
        type => 'hidden',
        value => 'Did not complete checkout',
        extra => $extra,
        mandatory => 0,
        weight => 100,
      );
      webform_component_insert($order_status_component);
    }
  }
}

/**
 * Clear all carts that have deleted webform products.
 */
function uc_webform_uc_cart_alter(&$items) {
  foreach ($items as $item) {
    if (isset($item->data['webform_sid'])) {
      $wf_exist = db_result(db_query("SELECT nid FROM {node} WHERE nid=%d", $item->data['webform_nid']));
      if (empty($wf_exist)) {
        db_query("DELETE FROM {uc_cart_products} WHERE cart_item_id = %d", $item->cart_item_id);
      }
    }
  }
}

/**
 * Clear all carts that have submissions from deleted webform node.
 */
function uc_webform_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  if ($node->type == 'webform') {
    switch ($op) {
      case 'delete':
        $result = db_query("SELECT * FROM {uc_cart_products}");
        while ($res = db_fetch_object($result)) {
          $data = unserialize($res->data);
          if ($node->nid == $data['webform_nid']) {
            db_query("DELETE FROM {uc_cart_products} WHERE cart_item_id = %d", $res->cart_item_id);
          }
        }
        break;
      default:
        break;
    }
  }
}

Functions

Namesort descending Description
theme_uc_webform_product_analysis Output the content of the Analysis page.
uc_webform_cart_item Implementation of hook_cart_item().
uc_webform_form_uc_cart_view_form_alter Implementation of hook_form_FORM_ID_alter().
uc_webform_menu Implementation of hook_menu().
uc_webform_nodeapi Clear all carts that have submissions from deleted webform node.
uc_webform_order Implementation of hook_order().
uc_webform_product_analysis Provides a simple analysis of submissions that contain products.
uc_webform_submission_delete_products_form Confirmation form before deleting products from a cart.
uc_webform_submission_delete_products_form_submit
uc_webform_theme Implementation of hook_theme().
uc_webform_theme_registry_alter Implementation of hook_theme_registry_alter().
uc_webform_uc_cart_alter Clear all carts that have deleted webform products.
uc_webform_webform_components_form Override 'theme_webform_components_form($form)', found in webform.components.inc. This function will need to be updated everytime quicksketch makes a corresponding change.
uc_webform_webform_component_info Implementation of hook_webform_component_info().
uc_webform_webform_component_insert Implementation of hook_webform_component_insert().
uc_webform_webform_component_update Respond to a Webform component being updated in the database.
uc_webform_webform_submission_insert Respond to a Webform submission being inserted.
_uc_webform_autocomplete_products Provides an auto-complete list of products that do not contain attributes.
_uc_webform_product_grid_orders Generate statistics for product_grid components, limited to checked out webforms. This information is displayed under the "orders" tab of the webform results.
_uc_webform_product_list_orders Statistics for product_list components, limited to checked out webforms.
_uc_webform_product_orders Generate statistics for product components, limited to checked out webforms.