Problem/Motivation
tl;dr: Customer profile data is not available in custom order form validation callbacks.
To reproduce:
1. Minimal drupal install.
2. drush en commerce_order_ui commerce_product_ui commerce_cart
3. Add a product at /admin/commerce/products/add/product.
4. Create a custom module with the following code:
function MYMODULE_form_commerce_order_ui_order_form_alter(&$form, $form_state) {
$form['actions']['submit']['#validate'][] = 'mytest_validate';
}
function mytest_validate($form, &$form_state) {
$order_w = entity_metadata_wrapper('commerce_order', $form_state['commerce_order']);
$a = $order_w->commerce_customer_billing->commerce_customer_address->value();
}
4. Go to /admin/commerce/orders/add and add a line item, fill out the billing address.
5. Submit the order form. We get:
EntityMetadataWrapperException: Unknown data property commerce_customer_address. in EntityStructureWrapper->getPropertyInfo() (line 335 of /sites/all/modules/entity/includes/entity.wrapper.inc).
The problem is that in mytest_validate() the commerce_customer_billing reference on the order is empty. This is caused by the form_set_value($element, array(), $form_state); call in commerce_customer_profile_manager_validate(). The early return; after this line also prevents the profile_id to be properly set in $form_state['values']['commerce_customer_billing'].
Note that this only happens when before submission an AJAX request is triggered on the order form.
This issue does not appear if validate functions do not try to access customer profiles.
My use case is trying to validate the order after drupal validation has passed using a remote service.
Proposed resolution
Try and set the profile_id on $form_state['values']['commerce_customer_billing'] even if we don't want to validate.
Comments
Comment #2
czigor CreditAttribution: czigor at Liip commentedComment #3
czigor CreditAttribution: czigor at Liip for FREITAG lab. AG commentedI wonder what makes the commerce_customer_profile_manager widget so special that it needs to check #limit_validation_errors of the triggering element in its #element_validate callback. There's no example for this in any of the contrib modules I've used: they only set #limit_validation_errors but never check its value. Should not be this the job of _form_validate()?
Comment #4
czigor CreditAttribution: czigor at Liip for FREITAG lab. AG commentedComment #5
mglamanI hit something close to this hell last week. Can you debug
commerce_order_commerce_customer_profile_presave()
to see if the act of preserving profile data is causing issue? For me it kept kicking back profile IDs.Comment #6
mglamanI'm wrong and can't read. It has to do with
Comment #7
mglamanGit blame for that section returns #1131884: commerce_customer_profile_manager_validate creates new profiles during ajax callbacks if no profile is set on the form.
Comment #8
mglamanTagging for the D7 sprint