? uc-rules.patch
? contrib/uc_unique_currency
? uc_cart/uc_cart.rules.inc
Index: ca/ca.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ubercart/ca/ca.module,v
retrieving revision 1.1.2.16
diff -u -p -r1.1.2.16 ca.module
--- ca/ca.module	22 Apr 2009 17:45:12 -0000	1.1.2.16
+++ ca/ca.module	25 May 2009 16:26:13 -0000
@@ -201,6 +201,17 @@ function ca_pull_trigger() {
     }
     $locked[$key] = TRUE;
   }
+  
+  // If Rules exists, invoke the rule event.
+  if (module_exists('rules')) {
+    // Check event exists in rules module.
+    $events = rules_get_events();
+    if ($events[$pid]) {
+      $rules_arguments = (array)$pid + $arguments;
+      call_user_func_array('rules_invoke_event', $rules_arguments);
+    }
+  }
+  
 
   return TRUE;
 }
Index: uc_cart/uc_cart.ca.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ubercart/uc_cart/uc_cart.ca.inc,v
retrieving revision 1.1.2.13
diff -u -p -r1.1.2.13 uc_cart.ca.inc
--- uc_cart/uc_cart.ca.inc	28 Apr 2009 21:03:14 -0000	1.1.2.13
+++ uc_cart/uc_cart.ca.inc	25 May 2009 16:26:13 -0000
@@ -23,7 +23,7 @@ function uc_cart_ca_condition() {
     '#arguments' => array(
       'order' => array(
         '#entity' => 'uc_order',
-        '#title' => t('Order'),
+        '#title' => t('order'),
       ),
     ),
   );
@@ -45,7 +45,7 @@ function uc_cart_ca_trigger() {
       ),
       'account' => array(
         '#entity' => 'user',
-        '#title' => t('Customer user account'),
+        '#title' => t('customer user account'),
       )
     ),
   );
Index: uc_order/uc_order.rules.inc
===================================================================
RCS file: uc_order/uc_order.rules.inc
diff -N uc_order/uc_order.rules.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ uc_order/uc_order.rules.inc	25 May 2009 16:26:14 -0000
@@ -0,0 +1,1147 @@
+<?php
+// $Id:$
+
+/**
+ * @file
+ * Rules integration with the Ubercart order module.
+ */
+
+
+/******************************************************************************
+ * Hooks implementations                                                      *
+ ******************************************************************************/
+
+/**
+ * Implementation of hook_rules_data_type_info().
+ */
+function uc_order_rules_data_type_info() {
+  return array(
+    'uc_order' => array(
+      'label' => t('ubercart order'),
+      'class' => 'rules_data_type_uc_order',
+      'savable' => TRUE,
+      'identifiable' => TRUE,
+      'module' => 'Ubercart order',
+    ),
+  );
+}
+
+/**
+ * Defines the Ubercart order data type.
+ */
+class rules_data_type_uc_order extends rules_data_type {
+  function load($order_id) {
+    return uc_order_load($order_id);
+  }
+  
+  function save($order) {
+    uc_order_save($order);
+  }
+
+  function get_identifier() {
+    $order = &$this->get();
+    return $order->oid;
+  }
+}
+
+
+/**
+ * Implementation of hook_rules_event_info().
+ */
+function uc_order_rules_event_info() {
+  $items['uc_order_status_update'] = array(
+    'label' => t('Order status gets updated'),
+    'arguments' => array(
+      'order' => array(
+        'type' => 'uc_order',
+        'label' => t('Original order'),
+      ),
+      'updated_order' => array(
+        'type' => 'uc_order',
+        'label' => t('Updated order'),
+      ),
+    ),
+    'module' => 'Ubercart order',    
+  );
+
+  $items['uc_order_status_email_update'] = array(
+    'label' => t('E-mail requested for order status update'),
+    'arguments' => array(
+      'order' => array(
+        'type' => 'uc_order',
+        'label' => t('Order'),
+      ),
+    ),
+    'module' => 'Ubercart order',    
+  );
+
+  return $items;
+}
+
+/**
+ * Implementation of hook_rules_condition_info().
+ */
+function uc_order_rules_condition_info() {
+  $order_arg = array(
+    'type' => 'uc_order',
+  );
+
+  $conditions['uc_order_rules_condition_status_condition'] = array(
+    'label' => t('Check the order status'),
+    'help' => t('Returns TRUE if the current order status matches the status specified below.'),    
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+
+  $conditions['uc_order_rules_condition_total'] = array(
+    'label' => t('Check the order total'),
+    'help' => t('Returns TRUE if the current order total is within the parameters below.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+
+  $conditions['uc_order_rules_condition_delivery_postal_code'] = array(
+    'label' => t("Check an order's shipping postal code"),
+    'help' => t('Returns TRUE if the shipping postal code is in the specified area.'),
+    'arguments' => array(
+      'order' => $order_arg
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_delivery_zone'] = array(
+    'label' => t("Check an order's shipping @zone", array('@zone' => uc_get_field_name('zone'))),
+    'help' => t('Returns TRUE if the shipping @zone is in the specified list.', array('@zone' => uc_get_field_name('zone'))),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_delivery_country'] = array(
+    'label' => t("Check an order's shipping country"),
+    'help' => t('Returns TRUE if the shipping country is in the specified list.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_billing_postal_code'] = array(
+    'label' => t("Check an order's billing postal code"),
+    'help' => t('Returns TRUE if the billing postal code is in the specified area.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_billing_zone'] = array(
+    'label' => t("Check an order's billing @zone", array('@zone' => uc_get_field_name('zone'))),
+    'help' => t('Returns TRUE if the billing @zone is in the specified list.', array('@zone' => uc_get_field_name('zone'))),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_billing_country'] = array(
+    'label' => t("Check an order's billing country"),
+    'help' => t('Returns TRUE if the billing country is in the specified list.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_has_products'] = array(
+    'label' => t("Check an order's products"),
+    'help' => t('Returns TRUE if the order has any, all, or only the products in the list.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_count_products'] = array(
+    'label' => t("Check an order's number of products"),
+    'help' => t('Determines if the order has the specified number of products, possibly of a certain type.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_products_weight'] = array(
+    'label' => t("Check an order's total weight"),
+    'help' => t('Determines if the order has the specified weight, possibly counting only a certain type of product.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_is_shippable'] = array(
+    'label' => t('Check if an order can be shipped'),
+    'help' => t('Returns TRUE if the order has any shippable products.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+
+  $conditions['uc_order_rules_condition_user_name'] = array(
+    'label' => t('Check the user name.'),
+    'help' => t('Returns TRUE if the user name matches the condition.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_user_mail'] = array(
+    'label' => t('Check the user email address.'),
+    'help' => t('Returns TRUE if the user email addresses matches the condition.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_user_created'] = array(
+    'label' => t('Check the user creation date.'),
+    'help' => t('Returns TRUE if the user creation date matches the condition.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_user_login'] = array(
+    'label' => t('Check the user last login date.'),
+    'help' => t('Returns TRUE if the user last login date matches the condition.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_user_language'] = array(
+    'label' => t('Check the user language setting.'),
+    '#category' => t('Order: User'),
+    'help' => t('Returns TRUE if the user language setting matches the condition.'),
+    'base' => 'uc_order_rules_condition_user_language',
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $conditions['uc_order_rules_condition_user_roles'] = array(
+    'label' => t('Check the role of the user.'),
+    'help' => t('Returns TRUE if the user roles match your settings.'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+
+  return $conditions;
+}
+
+/**
+ * Implementation of hook_rules_action_info().
+ */
+function uc_order_rules_action_info() {
+  $order_arg = array(
+    'type' => 'uc_order',
+    'label' => t('Order'),
+  );
+  
+  $actions['uc_order_rules_action_load_order'] = array(
+    'label' => t('Load order by ID'),
+    'new variables' => array(
+      'uc_order' => array(
+        'type' => 'uc_order',
+        'label' => t('loaded ubercart order'),
+      ),
+    ),
+    'module' => 'Ubercart order',    
+  );
+
+  $actions['uc_order_rules_action_update_status'] = array(
+    'label' => t('Update the order status'),
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $actions['uc_order_rules_action_add_comment'] = array(
+    'label' => t('Add a comment to the order'),    
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $actions['uc_order_email'] = array(
+    'label' => t('Send an order email'),    
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+  $actions['uc_order_email_invoice'] = array(
+    'label' => t('Email an order invoice'),    
+    'arguments' => array(
+      'order' => $order_arg,
+    ),
+    'module' => 'Ubercart order',    
+  );
+
+  return $actions;
+}
+
+
+/******************************************************************************
+ * Condition callbacks and forms                                              *
+ ******************************************************************************/
+
+ 
+/**
+ * Condition: Check the current order status. 
+ */
+function uc_order_rules_condition_check_order_status($order, $settings) {
+  // Return TRUE if the order status matches.
+  return $order->order_status == $settings['order_status'];
+}
+
+/**
+ * Condition: Check the current order status configuration form. 
+ */
+function uc_order_rules_condition_check_order_status_form($settings, &$form, $form_state) { 
+  foreach (uc_order_status_list('general') as $status) {
+    $options[$status['id']] = $status['title'];
+  }
+  foreach (uc_order_status_list('specific') as $status) {
+    $options[$status['id']] = $status['title'];
+  }
+  $form['settings']['order_status'] = array(
+    '#type' => 'select',
+    '#title' => t('Order status'),
+    '#options' => $options,
+    '#default_value' => $settings['order_status'],
+  );
+
+
+}
+
+// Check the current order balance.
+function uc_order_rules_condition_total($order, $settings) {
+  switch ($settings['order_total_comparison']) {
+    case 'less':
+      return $order->order_total < $settings['order_total_value'];
+    case 'less_equal':
+      return $order->order_total <= $settings['order_total_value'];
+    case 'equal':
+      return $order->order_total == $settings['order_total_value'];
+    case 'greater_equal':
+      return $order->order_total >= $settings['order_total_value'];
+    case 'greater':
+      return $order->order_total > $settings['order_total_value'];
+  }
+}
+
+function uc_order_rules_condition_total_form($settings, &$form, $form_state) { 
+  $form['settings']['order_total_value'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Order total value'),
+    '#description' => t('Specify a value to compare the order total against.'),
+    '#default_value' => $settings['order_total_value'],
+    '#size' => 16,
+    '#field_prefix' => variable_get('uc_sign_after_amount', FALSE) ? '' : variable_get('uc_currency_sign', '$'),
+    '#field_suffix' => variable_get('uc_sign_after_amount', FALSE) ? variable_get('uc_currency_sign', '$') : '',
+  );
+
+  $options = array(
+    'less' => t('Total is less than specified value.'),
+    'less_equal' => t('Total is less than or equal to specified value.'),
+    'equal' => t('Total is equal to specified value.'),
+    'greater_equal' => t('Total is greater than or equal to specified value.'),
+    'greater' => t('Total is greater than specified value.'),
+  );
+  $form['settings']['order_total_comparison'] = array(
+    '#type' => 'radios',
+    '#title' => t('Order total comparison type'),
+    '#options' => $options,
+    '#default_value' => isset($settings['order_total_comparison']) ? $settings['order_total_comparison'] : 'greater_equal',
+  );
+
+
+}
+
+// Check an order's delivery postal code.
+function uc_order_rules_condition_delivery_postal_code($order, $settings) {
+  // Trim the wildcard off the pattern.
+  $pattern = rtrim($settings['pattern'], '*');
+
+  // Return TRUE if the delivery postal code begins with the pattern.
+  return strpos($order->delivery_postal_code, $pattern) === 0;
+}
+
+function uc_order_rules_condition_delivery_postal_code_form($settings, &$form, $form_state) { 
+  $form['settings']['pattern'] = array(
+    '#type' => 'textfield',
+    '#title' => uc_get_field_name('postal_code'),
+    '#default_value' => $settings['pattern'],
+    '#description' => t('Specify a postal code or postal code pattern. Use "*" as a wild card to specify a range of postal codes.<br /><b>Example:</b> In the US, 402* represents all areas from 40200 to 40299.'),
+    '#size' => 15,
+  );
+
+
+}
+
+// Check an order's delivery zone.
+function uc_order_rules_condition_delivery_zone($order, $settings) {
+  return in_array($order->delivery_zone, $settings['zones']);
+}
+
+function uc_order_rules_condition_delivery_zone_form($settings, &$form, $form_state) { 
+  $result = db_query("SELECT z.*, c.country_name FROM {uc_zones} AS z LEFT JOIN {uc_countries} AS c ON z.zone_country_id = c.country_id ORDER BY c.country_name, z.zone_name");
+  while ($zone = db_fetch_object($result)) {
+    $options[$zone->country_name][$zone->zone_id] = $zone->zone_name;
+  }
+
+  $form['settings']['zones'] = array(
+    '#type' => 'select',
+    '#title' => uc_get_field_name('zone'),
+    '#options' => $options,
+    '#default_value' => $settings['zones'],
+    '#multiple' => TRUE,
+  );
+
+
+}
+
+// Check an order's delivery country.
+function uc_order_rules_condition_delivery_country($order, $settings) {
+  return in_array($order->delivery_country, $settings['countries']);
+}
+
+function uc_order_rules_condition_delivery_country_form($settings, &$form, $form_state) { 
+  $form['settings']['countries'] = uc_country_select(uc_get_field_name('country'));
+  $form['settings']['countries']['#default_value'] = $settings['countries'];
+  $form['settings']['countries']['#multiple'] = TRUE;
+
+}
+
+// Check an order's billing postal code.
+function uc_order_rules_condition_billing_postal_code($order, $settings) {
+  // Trim the wildcard off the pattern.
+  $pattern = rtrim($settings['pattern'], '*');
+
+  // Return TRUE if the delivery postal code begins with the pattern.
+  return strpos($order->billing_postal_code, $pattern) === 0;
+}
+
+function uc_order_rules_condition_billing_postal_code_form($settings, &$form, $form_state) { 
+  $form['settings']['pattern'] = array(
+    '#type' => 'textfield',
+    '#title' => uc_get_field_name('postal_code'),
+    '#default_value' => $settings['pattern'],
+    '#description' => t('Specify a postal code or postal code pattern. Use "*" as a wild card to specify a range of postal codes.<br /><b>Example:</b> In the US, 402* represents all areas from 40200 to 40299.'),
+    '#size' => 15,
+  );
+
+
+}
+
+// Check an order's billing zone.
+function uc_order_rules_condition_billing_zone($order, $settings) {
+  return in_array($order->billing_zone, $settings['zones']);
+}
+
+function uc_order_rules_condition_billing_zone_form($settings, &$form, $form_state) { 
+  $result = db_query("SELECT z.*, c.country_name FROM {uc_zones} AS z LEFT JOIN {uc_countries} AS c ON z.zone_country_id = c.country_id ORDER BY c.country_name, z.zone_name");
+  while ($zone = db_fetch_object($result)) {
+    $options[$zone->country_name][$zone->zone_id] = $zone->zone_name;
+  }
+
+  $form['settings']['zones'] = array(
+    '#type' => 'select',
+    '#title' => uc_get_field_name('zone'),
+    '#options' => $options,
+    '#default_value' => $settings['zones'],
+    '#multiple' => TRUE,
+  );
+
+
+}
+
+// Check an order's billing country.
+function uc_order_rules_condition_billing_country($order, $settings) {
+  return in_array($order->billing_country, $settings['countries']);
+}
+
+function uc_order_rules_condition_billing_country_form($settings, &$form, $form_state) {
+  $form['settings']['countries'] = uc_country_select(uc_get_field_name('country'));
+  $form['settings']['countries']['#default_value'] = $settings['countries'];
+  $form['settings']['countries']['#multiple'] = TRUE;
+}
+
+function uc_order_rules_condition_has_products($order, $settings) {
+  $products = array();
+  foreach ($order->products as $product) {
+    $products[] = $product->nid;
+  }
+  $required = array_intersect($settings['products'], $products);
+  if ($settings['required']) {
+    $required_check = $required == $settings['products'];
+  }
+  else {
+    $required_check = (bool)count($required);
+  }
+  if ($settings['forbidden']) {
+    $forbidden = array_diff($products, $settings['products']);
+    $forbidden_check = (bool)count($forbidden);
+  }
+  else {
+    $forbidden_check = FALSE;
+  }
+  return $required_check && !$forbidden_check;
+}
+
+function uc_order_rules_condition_has_products_form($settings, &$form, $form_state) { 
+  $settings += array('required' => 0, 'forbidden' => 0);
+  $form['settings']['required'] = array('#type' => 'radios',
+    '#title' => t('Require selected products'),
+    '#options' => array(
+      0 => t('Order has any of these products.'),
+      1 => t('Order has all of these products.'),
+    ),
+    '#default_value' => $settings['required'],
+  );
+  $form['settings']['forbidden'] = array('#type' => 'radios',
+    '#title' => t('Forbid other products'),
+    '#options' => array(
+      0 => t('Order may have other products.'),
+      1 => t('Order has only these products.'),
+    ),
+    '#default_value' => $settings['forbidden'],
+  );
+  $options = array();
+  $result = db_query("SELECT nid, model FROM {uc_products}");
+  while ($product = db_fetch_object($result)) {
+    $options[$product->nid] = $product->model;
+  }
+  $form['settings']['products'] = array('#type' => 'select',
+    '#title' => t('Products'),
+    '#options' => $options,
+    '#default_value' => $settings['products'],
+    '#multiple' => TRUE,
+  );
+
+}
+
+function uc_order_rules_condition_count_products($order, $settings) {
+  $totals = array('all' => 0);
+  $total = 0;
+  foreach ($order->products as $product) {
+    $totals['all'] += $product->qty;
+    $totals[$product->nid] = $product->qty;
+  }
+  if (in_array('all', $settings['products'])) {
+    $total = $totals['all'];
+  }
+  else {
+    foreach ($settings['products'] as $product) {
+      $total += $totals[$product];
+    }
+  }
+  switch ($settings['product_count_comparison']) {
+    case 'less':
+      return $total < $settings['product_count_value'];
+    case 'less_equal':
+      return $total <= $settings['product_count_value'];
+    case 'equal':
+      return $total == $settings['product_count_value'];
+    case 'greater_equal':
+      return $total >= $settings['product_count_value'];
+    case 'greater':
+      return $total > $settings['product_count_value'];
+  }
+}
+
+function uc_order_rules_condition_count_products_form($settings, &$form, $form_state) { 
+  $options = array('all' => t('- All products -'));
+  $result = db_query("SELECT nid, model FROM {uc_products} ORDER BY model");
+  while ($product = db_fetch_object($result)) {
+    $options[$product->nid] = $product->model;
+  }
+  $form['settings']['products'] = array('#type' => 'select',
+    '#title' => t('Products'),
+    '#options' => $options,
+    '#default_value' => $settings['products'],
+    '#description' => check_plain(t('Selecting "- All products -" will override any other selections and returns the total number of products in the order.')),
+    '#multiple' => TRUE,
+  );
+  $form['settings']['product_count_value'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Product count value'),
+    '#description' => t('Specify a value to compare the product count against.'),
+    '#default_value' => $settings['product_count_value'],
+    '#size' => 16,
+  );
+
+  $options = array(
+    'less' => t('Total is less than specified value.'),
+    'less_equal' => t('Total is less than or equal to specified value.'),
+    'equal' => t('Total is equal to specified value.'),
+    'greater_equal' => t('Total is greater than or equal to specified value.'),
+    'greater' => t('Total is greater than specified value.'),
+  );
+  $form['settings']['product_count_comparison'] = array(
+    '#type' => 'radios',
+    '#title' => t('Product count comparison type'),
+    '#options' => $options,
+    '#default_value' => isset($settings['product_count_comparison']) ? $settings['product_count_comparison'] : 'greater_equal',
+  );
+
+
+}
+
+function uc_order_rules_condition_products_weight($order, $settings) {
+  $totals = array('all' => 0);
+  $total = 0;
+  foreach ($order->products as $product) {
+    $unit_conversion = uc_weight_conversion($product->weight_units, $settings['weight_units']);
+    $totals['all'] += $product->qty * $product->weight * $unit_conversion;
+    $totals[$product->model] = $product->qty * $product->weight * $unit_conversion;
+  }
+  if (in_array('all', $settings['products'])) {
+    $total = $totals['all'];
+  }
+  else {
+    foreach ($settings['products'] as $product) {
+      $total += $totals[$product];
+    }
+  }
+  switch ($settings['product_weight_comparison']) {
+    case 'less':
+      return $total < $settings['product_weight_value'];
+    case 'less_equal':
+      return $total <= $settings['product_weight_value'];
+    case 'equal':
+      return $total == $settings['product_weight_value'];
+    case 'greater_equal':
+      return $total >= $settings['product_weight_value'];
+    case 'greater':
+      return $total > $settings['product_weight_value'];
+  }
+}
+
+function uc_order_rules_condition_products_weight_form($settings, &$form, $form_state) { 
+  $options = array('all' => t('- All products -'));
+  $result = db_query("SELECT nid, model FROM {uc_products}");
+  while ($product = db_fetch_object($result)) {
+    $options[$product->nid] = $product->model;
+  }
+  $form['settings']['products'] = array('#type' => 'select',
+    '#title' => t('Products'),
+    '#options' => $options,
+    '#default_value' => $settings['products'],
+    '#description' => check_plain(t('Selecting "- All products -" will override any other selections and returns the total number of products in the order.')),
+    '#multiple' => TRUE,
+  );
+  $form['settings']['weight_units'] = array('#type' => 'select',
+    '#title' => t('Unit of measurement'),
+    '#default_value' => $settings['weight_units'] ? $settings['weight_units'] : variable_get('uc_weight_unit', 'lb'),
+    '#options' => array(
+      'lb' => t('Pounds'),
+      'kg' => t('Kilograms'),
+      'oz' => t('Ounces'),
+      'g' => t('Grams'),
+    ),
+  );
+  $form['settings']['product_weight_value'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Product weight value'),
+    '#description' => t('Specify a value to compare the product weight against.'),
+    '#default_value' => $settings['product_weight_value'],
+    '#size' => 16,
+  );
+
+  $options = array(
+    'less' => t('Total is less than specified value.'),
+    'less_equal' => t('Total is less than or equal to specified value.'),
+    'equal' => t('Total is equal to specified value.'),
+    'greater_equal' => t('Total is greater than or equal to specified value.'),
+    'greater' => t('Total is greater than specified value.'),
+  );
+  $form['settings']['product_weight_comparison'] = array(
+    '#type' => 'radios',
+    '#title' => t('Product count comparison type'),
+    '#options' => $options,
+    '#default_value' => isset($settings['product_weight_comparison']) ? $settings['product_weight_comparison'] : 'greater_equal',
+  );
+
+
+}
+
+function uc_order_rules_condition_is_shippable($order, $settings) {
+  return uc_order_is_shippable($order);
+}
+
+// Check a user name
+function uc_order_rules_condition_user_name($order, $settings) {
+  if (empty($order->uid)) {
+    // Anonymous users have no names.
+    return empty($settings['name']);
+  }
+  else {
+    // Load from the order.
+    if ($account = uc_order_user_load($order)) {
+      return $account->name == $settings['name'];
+    }
+    // Or, if the user doesn't exist anymore, return FALSE
+    else {
+      return FALSE;
+    }
+  }
+}
+
+function uc_order_rules_condition_user_name_form($settings, &$form, $form_state) { 
+  $form['settings']['name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('User name'),
+    '#default_value' => isset($settings['name']) ? $settings['name'] : '',
+    '#autocomplete_path' => 'user/autocomplete',
+    '#description' => t('Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous', t('Anonymous')))),
+  );
+
+
+}
+
+// Check an user email
+function uc_order_rules_condition_user_mail($order, $settings) {
+  $account = uc_order_user_load($order);
+  return $account->mail == $settings['mail'];
+}
+
+function uc_order_rules_condition_user_mail_form($settings, &$form, $form_state) { 
+  $form['settings']['mail'] = array(
+    '#type' => 'textfield',
+    '#title' => t('User email'),
+    '#default_value' => isset($settings['mail']) ? $settings['mail'] : '',
+  );
+
+
+}
+
+// Check an user creation date
+function uc_order_rules_condition_user_created($order, $settings) {
+  $account = uc_order_user_load($order);
+
+  // Get the beginning of the day the user registered.
+  $user_created = $account->created - ($account->created % 86400);
+  $settings_created = gmmktime(0, 0, 0, $settings['created']['month'], $settings['created']['day'], $settings['created']['year']);
+
+  switch ($settings['operator']) {
+    case 'less':
+      return $user_created < $settings_created;
+    case 'less_equal':
+      return $user_created <= $settings_created;
+    case 'equal':
+      return $user_created == $settings_created;
+    case 'not_equal':
+      return $user_created != $settings_created;
+    case 'greater_equal':
+      return $user_created >= $settings_created;
+    case 'greater':
+      return $user_created > $settings_created;
+  }
+}
+
+function uc_order_rules_condition_user_created_form($settings, &$form, $form_state) { 
+  $form['settings']['operator'] = array(
+    '#type' => 'radios',
+    '#title' => t('Operator'),
+    '#options' => array(
+      'less' => t('User was created before the specified date.'),
+      'less_equal' => t('User was created on or before the specified date.'),
+      'equal' => t('User was created on the specified date.'),
+      'not_equal' => t('User was not created on the specified date.'),
+      'greater_equal' => t('User was created on or after the specified date.'),
+      'greater' => t('User was created after the specified date.'),
+    ),
+    '#default_value' => isset($settings['operator']) ? $settings['operator'] : 'equal',
+  );
+  $form['settings']['created'] = array(
+    '#type' => 'date',
+    '#title' => t('User creation date'),
+    '#default_value' => isset($settings['created']) ? $settings['created'] : '',
+  );
+
+
+}
+
+// Check an user last login date
+function uc_order_rules_condition_user_login($order, $settings) {
+  $account = uc_order_user_load($order);
+
+  // Get the beginning of the day the user last logged in.
+  $user_login = $account->login - ($account->login % 86400);
+  $settings_login = gmmktime(0, 0, 0, $settings['login']['month'], $settings['login']['day'], $settings['login']['year']);
+
+  switch ($settings['operator']) {
+    case 'less':
+      return $user_login < $settings_login;
+    case 'less_equal':
+      return $user_login <= $settings_login;
+    case 'equal':
+      return $user_login == $settings_login;
+    case 'not_equal':
+      return $user_login != $settings_login;
+    case 'greater_equal':
+      return $user_login >= $settings_login;
+    case 'greater':
+      return $user_login > $settings_login;
+  }
+}
+
+function uc_order_rules_condition_user_login_form($settings, &$form, $form_state) { 
+  $form['settings']['operator'] = array(
+    '#type' => 'radios',
+    '#title' => t('Operator'),
+    '#options' => array(
+      'less' => t('User last logged in before the specified date.'),
+      'less_equal' => t('User last logged in on, or before the specified date.'),
+      'equal' => t('User last logged in on the specified date.'),
+      'not_equal' => t('User did not log in last on the specified date.'),
+      'greater_equal' => t('User last logged in on or after the specified date.'),
+      'greater' => t('User last logged after the specified date.'),
+    ),
+    '#default_value' => isset($settings['operator']) ? $settings['operator'] : 'equal',
+  );
+  $form['settings']['login'] = array(
+    '#type' => 'date',
+    '#title' => t('User last login date'),
+    '#default_value' => isset($settings['created']) ? $settings['created'] : '',
+  );
+
+
+}
+
+// Check an user language setting
+function uc_order_rules_condition_user_language($order, $settings) {
+  $account = uc_order_user_load($order);
+  $user_prefered_language = user_preferred_language($account);
+  return $user_prefered_language->language == $settings['language'];
+}
+
+function uc_order_rules_condition_user_language_form($settings, &$form, $form_state) { 
+  $languages = language_list();
+  $options = array();
+  foreach ($languages as $language) {
+    $options[$language->language] = $language->name.' ('.$language->native.')';
+  }
+  $form['settings']['language'] = array(
+    '#type' => 'select',
+    '#title' => t('User language setting'),
+    '#options' => $options,
+    '#default_value' => isset($settings['language']) ? $settings['language'] : '',
+  );
+
+
+}
+
+// Check an user roles.
+function uc_order_rules_condition_user_roles($order, $settings) {
+  $account = uc_order_user_load($order);
+  $settings['roles'] = array_filter($settings['roles']);
+
+  if ($settings['operator'] == 'AND') {
+    foreach ($settings['roles'] as $key) {
+      if (!isset($account->roles[$key])) {
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+  else {
+    foreach ($settings['roles'] as $key) {
+      if (isset($account->roles[$key])) {
+        return TRUE;
+      }
+    }
+    return FALSE;
+  }
+}
+
+function uc_order_rules_condition_user_roles_form($settings, &$form, $form_state) { 
+  $form['settings']['operator'] = array(
+    '#type' => 'radios',
+    '#title' => t('Operator'),
+    '#description' => t('If you use an <em>AND</em> case and want to check a custom role, make sure <em>authenticated user</em> is checked too or the condition will return FALSE.'),
+    '#options' => array(
+      'AND' => t('AND: If the user has all of these roles.'),
+      'OR' => t('OR: If the user has any of these roles.'),
+    ),
+    '#default_value' => isset($settings['operator']) ? $settings['operator'] : 'AND',
+  );
+  $form['settings']['roles'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Roles'),
+    '#options' => user_roles(),
+    '#default_value' => isset($settings['roles']) ? $settings['roles'] : array(),
+  );
+
+
+}
+
+/******************************************************************************
+ * Action Callbacks and Forms                                                 *
+ ******************************************************************************/
+
+function uc_order_rules_action_load_order($settings) {
+  if ($order = uc_order_load($settings['order_id'])) {
+    return array('uc_order' => $order);
+  }
+}
+
+function uc_order_rules_action_load_order_form($settings, &$form, $form_state) { 
+  $settings += array('order_id' => '');
+  $form['settings']['order_id'] = array(
+    '#type' => 'textfield',
+    '#description' => t('Enter the order ID that should be loaded.'),
+    '#title' => t('Order ID'),
+    '#required' => TRUE,
+    '#default_value' => $settings['order_id'],
+  );
+}
+
+// Update an order's status.
+function uc_order_rules_action_update_status(&$order, $settings) {
+  if (uc_order_update_status($order->order_id, $settings['order_status'])) {
+    $order->order_status = $settings['order_status'];
+  }
+}
+
+function uc_order_rules_action_update_status_form($settings, &$form, $form_state) { 
+  foreach (uc_order_status_list('general') as $status) {
+    $options[$status['id']] = $status['title'];
+  }
+  foreach (uc_order_status_list('specific') as $status) {
+    $options[$status['id']] = $status['title'];
+  }
+  $form['settings']['order_status'] = array(
+    '#type' => 'select',
+    '#title' => t('Order status'),
+    '#options' => $options,
+    '#default_value' => $settings['order_status'],
+  );
+
+
+}
+
+// Add a comment to an order.
+function uc_order_rules_action_add_comment($order, $settings) {
+  uc_order_comment_save($order->order_id, 0,
+    token_replace_multiple($settings['comment'], array('global' => NULL, 'order' => $order)),
+    $settings['comment_type'] == 'admin' ? 'admin' : 'order',
+    $order->order_status, $settings['comment_type'] == 'notified');
+}
+
+function uc_order_rules_action_add_comment_form($settings, &$form, $form_state) { 
+  $form['settings']['comment_type'] = array(
+    '#type' => 'radios',
+    '#title' => t('Select an order comment type'),
+    '#options' => array(
+      'admin' => t('Enter this as an admin comment.'),
+      'order' => t('Enter this as a customer order comment.'),
+      'notified' => t('Enter this as a customer order comment with a notified icon.'),
+    ),
+    '#default_value' => $settings['comment_type'],
+  );
+  $form['settings']['comment'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Comment'),
+    '#description' => t('Enter the comment message. Uses <a href="!url">order and global tokens</a>.', array('!url' => url('admin/store/help/tokens'))),
+    '#default_value' => $settings['comment'],
+  );
+
+
+}
+
+/**
+ * Send an email concerning an order.
+ *
+ * The recipients, subject, and message fields take order token replacements.
+ */
+function uc_order_rules_action_email($order, $settings) {
+  $account = user_load(array('uid' => $order->uid));
+  $language = language_default();
+
+  // Token replacements for the subject and body
+  $settings['replacements'] = array(
+    'global' => NULL,
+    'order' => $order,
+    'user' => $account,
+  );
+
+  // Apply token replacements to from and recipient e-mail addressses.
+  $from = token_replace_multiple($settings['from'], $settings['replacements']);
+  $addresses = token_replace_multiple($settings['addresses'], $settings['replacements']);
+
+  // Split up our recipient e-mail addresses.
+  $recipients = array();
+  foreach (explode("\n", $addresses) as $address) {
+    $recipients[] = trim($address);
+  }
+
+  foreach ($recipients as $email) {
+    $sent = drupal_mail('uc_order', 'action-mail', $email, $language, $settings, empty($from) ? uc_store_email_from() : $from);
+
+    if (!$sent['result']) {
+      watchdog('ca', 'Attempt to e-mail @email concerning order @order_id failed.', array('@email' => $email, '@order_id' => $order->order_id), WATCHDOG_ERROR);
+    }
+  }
+}
+
+function uc_order_rules_action_email_form($settings, &$form, $form_state) { 
+  $form['settings']['from'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Sender'),
+    '#default_value' => isset($settings['from']) ? $settings['from'] : uc_store_email_from(),
+    '#description' => t('The "From" address.'),
+    '#required' => TRUE,
+  );
+  $form['settings']['addresses'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Recipients'),
+    '#default_value' => isset($settings['addresses']) ? $settings['addresses'] : '[order-email]',
+    '#description' => t('Enter the email addresses to receive the notifications, one on each line. You may use order tokens for dynamic email addresses.'),
+    '#required' => TRUE,
+  );
+  $form['settings']['subject'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Subject'),
+    '#default_value' => $settings['subject'],
+    '#required' => TRUE,
+  );
+  $form['settings']['message'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Message'),
+    '#default_value' => $settings['message'],
+  );
+
+  // We add the #is_format element to allow us to locate and configure the filters.
+  $form['settings']['format'] = filter_form($settings['format']) + array('#is_format' => TRUE);
+
+  $form['settings']['token_help'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Replacement patterns'),
+    '#description' => t('You can make use of the replacement patterns in the e-mail from and recipients fields, the subject, and the message body.'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  foreach (array('global', 'order') as $name) {
+    $form['settings']['token_help'][$name] = array(
+      '#type' => 'fieldset',
+      '#title' => t('@name replacement patterns', array('@name' => drupal_ucfirst($name))),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    );
+    $form['settings']['token_help'][$name]['content'] = array(
+      '#value' => theme('token_help', $name),
+    );
+  }
+
+
+}
+
+/**
+ * Email an invoice.
+ *
+ * The subject and addresses fields take order token replacements.
+ */
+function uc_order_rules_action_email_invoice($order, $settings) {
+  $language = user_preferred_language($account);
+
+  // Token replacements for the subject and body
+  $settings['replacements'] = array(
+    'global' => NULL,
+    'order' => $order,
+  );
+
+  $recipients = array();
+  $addresses = token_replace_multiple($settings['addresses'], $settings['replacements']);
+
+  foreach (explode("\n", $addresses) as $address) {
+    $recipients[] = trim($address);
+  }
+
+  $settings['message'] = uc_order_load_invoice($order, $settings['view'], $settings['template']);
+
+  if (empty($recipients)) {
+    watchdog('ca', 'Attempted to e-mail an invoice with no recipient.', array(), WATCHDOG_ERROR);
+    return;
+  }
+
+  foreach ($recipients as $email) {
+    $sent = drupal_mail('uc_order', 'action-mail', $email, $language, $settings, empty($settings['from']) ? uc_store_email_from() : $settings['from']);
+
+    if (!$sent['result']) {
+      watchdog('ca', 'Attempt to e-mail invoice for order @order_id to @email failed.', array('@email' => $email, '@order_id' => $order->order_id), WATCHDOG_ERROR);
+    }
+  }
+}
+
+function uc_order_rules_action_email_invoice_form($settings, &$form, $form_state) { 
+  $form['settings']['from'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Sender'),
+    '#default_value' => isset($settings['from']) ? $settings['from'] : uc_store_email_from(),
+    '#description' => t('The "From" address.'),
+    '#required' => TRUE,
+  );
+  $form['settings']['addresses'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Recipients'),
+    '#default_value' => isset($settings['addresses']) ? $settings['addresses'] : '[order-email]',
+    '#description' => t('Enter the email addresses to receive the notifications, one on each line. You may use order tokens for dynamic email addresses.'),
+    '#required' => TRUE,
+  );
+  $form['settings']['subject'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Subject'),
+    '#default_value' => $settings['subject'],
+    '#required' => TRUE,
+  );
+
+  $form['settings']['token_help'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Replacement patterns'),
+    '#description' => t('You can make use of the replacement patterns in the recipients, the subject, and the template file.'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  foreach (array('global', 'order') as $name) {
+    $form['settings']['token_help'][$name] = array(
+      '#type' => 'fieldset',
+      '#title' => t('@name replacement patterns', array('@name' => drupal_ucfirst($name))),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    );
+    $form['settings']['token_help'][$name]['content'] = array(
+      '#value' => theme('token_help', $name),
+    );
+  }
+
+  $form['settings']['template'] = array(
+    '#type' => 'select',
+    '#title' => t('Invoice template'),
+    '#description' => t('Select the invoice template to use for this email.'),
+    '#options' => uc_order_template_options(),
+    '#default_value' => $settings['template'],
+  );
+  $form['settings']['view'] = array(
+    '#type' => 'radios',
+    '#title' => t('Included information'),
+    '#options' => array(
+      'print' => t('Show the business header and shipping method.'),
+      'admin-mail' => t('Show all of the above plus the help text, email text, and store footer.'),
+      'checkout-mail' => t('Show all of the above plus the "thank you" message.'),
+    ),
+    '#default_value' => $settings['view'],
+  );
+}
