? ec_store/.DS_Store
Index: ec_common/ec_common.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ecommerce/ec_common/ec_common.module,v
retrieving revision 1.7.2.30
diff -u -r1.7.2.30 ec_common.module
--- ec_common/ec_common.module	16 Dec 2010 14:25:02 -0000	1.7.2.30
+++ ec_common/ec_common.module	3 Jan 2011 03:37:11 -0000
@@ -105,6 +105,27 @@
 }
 
 /**
+ * Implementation of hook_elements().
+ */
+function ec_common_elements() {
+  $types = array();
+  
+  $types['checkbox'] = array('#process' => array('ec_common_process_external_required'));
+  $types['checkboxes'] = array('#process' => array('ec_common_process_external_required'));
+  $types['date'] = array('#process' => array('ec_common_process_external_required'));
+  $types['password'] = array('#process' => array('ec_common_process_external_required'));
+  $types['password_confirm'] = array('#process' => array('ec_common_process_external_required'));
+  $types['radio'] = array('#process' => array('ec_common_process_external_required'));
+  $types['radios'] = array('#process' => array('ec_common_process_external_required'));
+  $types['select'] = array('#process' => array('ec_common_process_external_required'));
+  $types['textarea'] = array('#process' => array('ec_common_process_external_required'));
+  $types['textfield'] = array('#process' => array('ec_common_process_external_required'));
+  $types['weight'] = array('#process' => array('ec_common_process_external_required'));
+  
+  return $types;
+}
+
+/**
  * Implementation of hook_views_api().
  */
 function ec_common_views_api() {
@@ -364,9 +385,32 @@
   return $prefix . $a;
 }
 
-function ec_common_display_as_required($elements) {
-  $elements['#required'] = TRUE;
-  return $elements;
+function ec_common_process_external_required($element) {
+  if (isset($element['#required_external']) && $element['#required_external']) {
+    if (isset($element['#pre_render'])) {
+      $element['#pre_render'][] = 'ec_common_pre_render_required_external';
+    }
+    else {
+      $element['#pre_render'] = array('ec_common_pre_render_required_external');
+    }
+    if (isset($element['#post_render'])) {
+      $element['#post_render'][] = 'ec_common_post_render_required_external';
+    }
+    else {
+      $element['#post_render'] = array('ec_common_post_render_required_external');
+    }
+  }
+  return $element;
+}
+
+function ec_common_pre_render_required_external($element) {
+  $element['#required'] = TRUE;
+  return $element;
+}
+
+function ec_common_post_render_required_external($content, &$element) {
+  $element['#required'] = FALSE;
+  return $content;
 }
 
 /**
Index: ec_charge/modules/node.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ecommerce/ec_charge/modules/node.inc,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 node.inc
--- ec_charge/modules/node.inc	16 Dec 2010 11:55:57 -0000	1.1.2.8
+++ ec_charge/modules/node.inc	3 Jan 2011 03:37:11 -0000
@@ -31,7 +31,7 @@
     '#title' => t('Node ids'),
     '#default_value' => $settings['nids'],
     '#description' => t('Enter in a comma separated list of nid which will when they are a product will be selected.'),
-    '#pre_render' => array('ec_common_display_as_required'),
+    '#required_external' => TRUE,
   );
 
   return $form;
Index: ec_customer/ec_customer.checkout.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ecommerce/ec_customer/ec_customer.checkout.inc,v
retrieving revision 1.1.2.48
diff -u -r1.1.2.48 ec_customer.checkout.inc
--- ec_customer/ec_customer.checkout.inc	16 Dec 2010 11:55:58 -0000	1.1.2.48
+++ ec_customer/ec_customer.checkout.inc	3 Jan 2011 03:37:12 -0000
@@ -116,7 +116,7 @@
         'method' => 'replace',
       ),
     );
-  }
+  }  
 
   // load the js to update the states
   module_load_include('inc', 'ec_store');
@@ -129,9 +129,9 @@
 function ec_customer_checkout_validate(&$form, &$form_state) {
   $txn = & $form_state['txn'];
   if (variable_get('ec_customer_billing_address', 1) || $txn->shippable) {
+    module_load_include('inc', 'ec_store');
     foreach ($form_state['values']['address'] as $type => $address) {
       if (empty($txn->{$type . '_address'}) && ($type != 'shipping' || !$form_state['values']['address']['billing']['use_for_shipping'])) {
-        module_load_include('inc', 'ec_store');
         ec_store_address_form_validate($form['ec_customer']['address'][$type], $address);
       }
     }
Index: ec_customer/ec_customer.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ecommerce/ec_customer/ec_customer.test,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 ec_customer.test
--- ec_customer/ec_customer.test	16 Dec 2010 11:55:58 -0000	1.1.2.2
+++ ec_customer/ec_customer.test	3 Jan 2011 03:37:12 -0000
@@ -34,4 +34,62 @@
     $this->drupalPost(NULL, $params, t('Update order'));
     $this->assertFieldByName('mail', $params['mail']);
   }
-}
\ No newline at end of file
+}
+
+class ecCustomerTestUpdateShippable extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Update address on shippable products'),
+      'description' => t('Check that using the \'Use this address as the shipping address\' on checkout will not cause errors on update/checkout'),
+      'group' => t('e-Commerce'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('ec_product', 'ec_anon', 'ec_checkout', 'ec_buynow', 'ec_receipt', 'ec_store', 'ec_common', 'ec_receipt_test_payment', 'ec_customer', 'ec_address', 'search', 'ctools');
+    drupal_install_modules(array('rules', 'views'));
+    variable_set('ec_default_currency', 'USD');
+    variable_set('rules_debug', 1);
+    
+    $info = ec_product_get_types('type', 'tangible');
+    ec_product_feature_enable($info, 'shippable');
+  }
+
+  function testTangiblePurchase() {
+    $account = $this->drupalCreateUser();
+    $this->drupalLogin($account);
+
+    $product = array(
+      'type' => 'product',
+      'ptype' => 'tangible',
+      'price' => '20.00',
+      'revision' => 1,
+    );
+
+    $node = $this->drupalCreateNode($product);
+    
+    $this->drupalGet('node/'. $node->nid);
+    $this->clickLink(t('Buy now'));
+
+    $params = array();
+    foreach (array(
+      'firstname' => $this->randomName(20),
+      'lastname' => $this->randomName(20),
+      'street1' => $this->randomName(52),
+      'street2' => $this->randomName(52),
+      'zip' => drupal_substr($this->randomName(10), -10),
+      'city' => $this->randomName(20),
+      'state' => 'CA',
+      'country' => 'US',
+    ) as $key => $value) {
+      $params['address[billing]['. $key .']'] = $value;
+    }
+    $params['address[billing][use_for_shipping]'] = 1;
+    $this->drupalPost(NULL, $params, t('Update order'));
+    
+    $this->assertNoText('Shipping First name field is required.', 'Required field shipping first name field has caused form error');
+    $this->assertNoText('Shipping Last name field is required.', 'Required field shipping last name field has caused form error');
+    $this->assertNoText('Shipping Street field is required.', 'Required field shipping street field has caused form error');
+    $this->assertNoText('Shipping City field is required.', 'Required field shipping city field has caused form error');
+  }
+}
Index: ec_store/ec_store.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ecommerce/ec_store/ec_store.inc,v
retrieving revision 1.5.2.28
diff -u -r1.5.2.28 ec_store.inc
--- ec_store/ec_store.inc	16 Dec 2010 11:55:58 -0000	1.5.2.28
+++ ec_store/ec_store.inc	3 Jan 2011 03:37:12 -0000
@@ -101,7 +101,7 @@
     '#default_value' => $address['firstname'],
     '#size'          => 32,
     '#maxlength'     => 32,
-    '#required' => TRUE,
+    '#required_external' => TRUE,
   );
   $form['lastname'] = array(
     '#type'          => 'textfield',
@@ -109,7 +109,7 @@
     '#default_value' => $address['lastname'],
     '#size'          => 32,
     '#maxlength'     => 32,
-    '#required' => TRUE,
+    '#required_external' => TRUE,
   );
   $form['country'] = array(
     '#type'          => 'select',
@@ -126,7 +126,7 @@
     '#default_value' => $address['street1'],
     '#size'          => 60,
     '#maxlength'     => 64,
-    '#required' => TRUE,
+    '#required_external' => TRUE,
   );
   $form['street2'] = array(
     '#type'          => 'textfield',
@@ -140,7 +140,7 @@
     '#default_value' => $address['city'],
     '#size'          => 32,
     '#maxlength'     => 32,
-    '#required' => TRUE,
+    '#required_external' => TRUE,
   );
   $state_select = array(
     '#type'          => 'select',
@@ -181,9 +181,15 @@
 }
 
 function ec_store_address_form_validate(&$form, &$values) {
+  foreach (array('firstname', 'lastname', 'street1', 'city') as $field) {
+    if (isset($values[$field]) && !$values[$field]) {
+      form_error($form[$field], t('!type !name field is required.', array('!name' => $form[$field]['#title'], '!type' => drupal_ucfirst($form['#address_type']))));
+    }
+  }
+
   if (!variable_get('store_ignore_state', FALSE)) {
     if (($info = ec_store_get_region_info($values['country'])) && empty($info['states'][drupal_strtoupper($values['state'])])) {
-      form_set_error(implode('][', $form['state']['#parents']), t('Please select a state'));
+      form_set_error(implode('][', $form['state']['#parents']), t('Please select a !type state', array('!type' => $form['#address_type'])));
     }
     // we need to re-add the javascript if we get an error due to the way this form is called
     ec_store_address_add_js();
