diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module
index 9e22e46..270a1ff 100644
--- a/modules/cart/commerce_cart.module
+++ b/modules/cart/commerce_cart.module
@@ -359,6 +359,16 @@ function commerce_cart_form_field_ui_field_edit_form_alter(&$form, &$form_state)
),
),
);
+ $form['instance']['commerce_cart_settings']['single_product_display'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Display the widget if there is only product being displayed.'),
+ '#default_value' => $commerce_cart_settings['single_product_display'],
+ '#states' => array(
+ 'visible' => array(
+ ':input[name="instance[commerce_cart_settings][attribute_field]"]' => array('checked' => TRUE),
+ ),
+ ),
+ );
$form['field']['cardinality']['#description'] .= '
' . t('Must be 1 for this field to function as an attribute selection field on Add to Cart forms.');
}
@@ -1436,342 +1446,329 @@ function commerce_cart_add_to_cart_form($form, &$form_state, $line_item, $show_q
);
}
else {
- // If the form is for a single product, store the product_id in a hidden
- // form field for use by the submit handler.
- if (count($products) == 1) {
- $form_state['default_product'] = reset($products);
+ // Attempt to use smart select boxes for the product selection. If the
+ // products are all of the same type and there are qualifying fields on
+ // that product type, display their options for customer selection.
+ $qualifying_fields = array();
+ $same_type = TRUE;
+ $type = '';
+
+ // Find the default product so we know how to set default options on the
+ // various Add to Cart form widgets and an array of any matching product
+ // based on attribute selections so we can add a selection widget.
+ $matching_products = array();
+ $default_product = NULL;
+ $attribute_names = array();
+ $unchanged_attributes = array();
+
+ foreach ($products as $product_id => $product) {
+ $product_wrapper = entity_metadata_wrapper('commerce_product', $product);
+
+ // Store the first product type.
+ if (empty($type)) {
+ $type = $product->type;
+ }
- $form['product_id'] = array(
- '#type' => 'hidden',
- '#value' => key($products),
- );
- }
- else {
- // However, if more than one products are represented on it, attempt to
- // use smart select boxes for the product selection. If the products are
- // all of the same type and there are qualifying fields on that product
- // type, display their options for customer selection.
- $qualifying_fields = array();
- $same_type = TRUE;
- $type = '';
-
- // Find the default product so we know how to set default options on the
- // various Add to Cart form widgets and an array of any matching product
- // based on attribute selections so we can add a selection widget.
- $matching_products = array();
- $default_product = NULL;
- $attribute_names = array();
- $unchanged_attributes = array();
+ // If the current product type is different from the first, we are not
+ // dealing with a set of same typed products.
+ if ($product->type != $type) {
+ $same_type = FALSE;
+ }
- foreach ($products as $product_id => $product) {
- $product_wrapper = entity_metadata_wrapper('commerce_product', $product);
+ // If the form state contains a set of attribute data, use it to try
+ // and determine the default product.
+ $changed_attribute = NULL;
- // Store the first product type.
- if (empty($type)) {
- $type = $product->type;
- }
+ if (!empty($form_state['values']['attributes'])) {
+ $match = TRUE;
- // If the current product type is different from the first, we are not
- // dealing with a set of same typed products.
- if ($product->type != $type) {
- $same_type = FALSE;
+ // Set an array of checked attributes for later comparison against the
+ // default matching product.
+ if (empty($attribute_names)) {
+ $attribute_names = (array) array_diff_key($form_state['values']['attributes'], array('product_select' => ''));
+ $unchanged_attributes = $form_state['values']['unchanged_attributes'];
}
- // If the form state contains a set of attribute data, use it to try
- // and determine the default product.
- $changed_attribute = NULL;
+ foreach ($attribute_names as $key => $value) {
+ // If this is the attribute widget that was changed...
+ if ($value != $unchanged_attributes[$key]) {
+ // Store the field name.
+ $changed_attribute = $key;
+ }
- if (!empty($form_state['values']['attributes'])) {
- $match = TRUE;
+ // If a field name has been stored and we've moved past it to
+ // compare the next attribute field...
+ if (!empty($changed_attribute) && $changed_attribute != $key) {
+ // Wipe subsequent values from the form state so the attribute
+ // widgets can use the default values from the new default product.
+ unset($form_state['input']['attributes'][$key]);
- // Set an array of checked attributes for later comparison against the
- // default matching product.
- if (empty($attribute_names)) {
- $attribute_names = (array) array_diff_key($form_state['values']['attributes'], array('product_select' => ''));
- $unchanged_attributes = $form_state['values']['unchanged_attributes'];
+ // Don't accept this as a matching product.
+ continue;
}
- foreach ($attribute_names as $key => $value) {
- // If this is the attribute widget that was changed...
- if ($value != $unchanged_attributes[$key]) {
- // Store the field name.
- $changed_attribute = $key;
- }
-
- // If a field name has been stored and we've moved past it to
- // compare the next attribute field...
- if (!empty($changed_attribute) && $changed_attribute != $key) {
- // Wipe subsequent values from the form state so the attribute
- // widgets can use the default values from the new default product.
- unset($form_state['input']['attributes'][$key]);
+ if ($product_wrapper->{$key}->raw() != $value) {
+ $match = FALSE;
+ }
+ }
- // Don't accept this as a matching product.
- continue;
- }
+ // If the changed field name has already been stored, only accept the
+ // first matching product by ignoring the rest that would match. An
+ // exception is granted for additional matching products that share
+ // the exact same attribute values as the first.
+ if ($match && !empty($changed_attribute) && !empty($matching_products)) {
+ reset($matching_products);
+ $matching_product = $matching_products[key($matching_products)];
+ $matching_product_wrapper = entity_metadata_wrapper('commerce_product', $matching_product);
- if ($product_wrapper->{$key}->raw() != $value) {
+ foreach ($attribute_names as $key => $value) {
+ if ($product_wrapper->{$key}->raw() != $matching_product_wrapper->{$key}->raw()) {
$match = FALSE;
}
}
+ }
- // If the changed field name has already been stored, only accept the
- // first matching product by ignoring the rest that would match. An
- // exception is granted for additional matching products that share
- // the exact same attribute values as the first.
- if ($match && !empty($changed_attribute) && !empty($matching_products)) {
- reset($matching_products);
- $matching_product = $matching_products[key($matching_products)];
- $matching_product_wrapper = entity_metadata_wrapper('commerce_product', $matching_product);
-
- foreach ($attribute_names as $key => $value) {
- if ($product_wrapper->{$key}->raw() != $matching_product_wrapper->{$key}->raw()) {
- $match = FALSE;
- }
- }
- }
-
- if ($match) {
- $matching_products[$product_id] = $product;
- }
+ if ($match) {
+ $matching_products[$product_id] = $product;
}
}
+ }
- // Set the default product now if it isn't already set.
- if (empty($matching_products)) {
- // If a product ID value was passed in, use that product if it exists.
- if (!empty($form_state['values']['product_id']) &&
- !empty($products[$form_state['values']['product_id']])) {
- $default_product = $products[$form_state['values']['product_id']];
- }
- elseif (empty($form_state['values']) &&
- !empty($line_item_wrapper->commerce_product) &&
- !empty($products[$line_item_wrapper->commerce_product->raw()])) {
- // If this is the first time the form is built, attempt to use the
- // product specified by the line item.
- $default_product = $products[$line_item_wrapper->commerce_product->raw()];
- }
- else {
- reset($products);
- $default_product = $products[key($products)];
- }
+ // Set the default product now if it isn't already set.
+ if (empty($matching_products)) {
+ // If a product ID value was passed in, use that product if it exists.
+ if (!empty($form_state['values']['product_id']) &&
+ !empty($products[$form_state['values']['product_id']])) {
+ $default_product = $products[$form_state['values']['product_id']];
+ }
+ elseif (empty($form_state['values']) &&
+ !empty($line_item_wrapper->commerce_product) &&
+ !empty($products[$line_item_wrapper->commerce_product->raw()])) {
+ // If this is the first time the form is built, attempt to use the
+ // product specified by the line item.
+ $default_product = $products[$line_item_wrapper->commerce_product->raw()];
}
else {
- // If the product selector has a value, use that.
- if (!empty($form_state['values']['attributes']['product_select']) &&
- !empty($products[$form_state['values']['attributes']['product_select']]) &&
- in_array($products[$form_state['values']['attributes']['product_select']], $matching_products)) {
- $default_product = $products[$form_state['values']['attributes']['product_select']];
- }
- else {
- reset($matching_products);
- $default_product = $matching_products[key($matching_products)];
- }
+ reset($products);
+ $default_product = $products[key($products)];
}
+ }
+ else {
+ // If the product selector has a value, use that.
+ if (!empty($form_state['values']['attributes']['product_select']) &&
+ !empty($products[$form_state['values']['attributes']['product_select']]) &&
+ in_array($products[$form_state['values']['attributes']['product_select']], $matching_products)) {
+ $default_product = $products[$form_state['values']['attributes']['product_select']];
+ }
+ else {
+ reset($matching_products);
+ $default_product = $matching_products[key($matching_products)];
+ }
+ }
- // Wrap the default product for later use.
- $default_product_wrapper = entity_metadata_wrapper('commerce_product', $default_product);
-
- $form_state['default_product'] = $default_product;
-
- // If all the products are of the same type...
- if ($same_type) {
- // Loop through all the field instances on that product type.
- foreach (field_info_instances('commerce_product', $type) as $name => $instance) {
- // A field qualifies if it is single value, required and uses a widget
- // with a definite set of options. For the sake of simplicity, this is
- // currently restricted to fields defined by the options module.
- $field = field_info_field($instance['field_name']);
-
- // Get the array of Cart settings pertaining to this instance.
- $commerce_cart_settings = commerce_cart_field_instance_attribute_settings($instance);
-
- // If the instance is of a field type that is eligible to function as
- // a product attribute field and if its attribute field settings
- // specify that this functionality is enabled...
- if (commerce_cart_field_attribute_eligible($field) && $commerce_cart_settings['attribute_field']) {
- // Get the options properties from the options module and store the
- // options for the instance in select list format in the array of
- // qualifying fields.
- $properties = _options_properties('select', FALSE, TRUE, TRUE);
-
- // Try to fetch localized names.
- $allowed_values = NULL;
-
- // Prepare translated options if using the i18n_field module.
- if (module_exists('i18n_field')) {
- if (($translate = i18n_field_type_info($field['type'], 'translate_options'))) {
- $allowed_values = $translate($field);
- _options_prepare_options($allowed_values, $properties);
- }
-
- // Translate the field title if set.
- if (!empty($instance['label'])) {
- $instance['label'] = i18n_field_translate_property($instance, 'label');
- }
+ // Wrap the default product for later use.
+ $default_product_wrapper = entity_metadata_wrapper('commerce_product', $default_product);
+
+ $form_state['default_product'] = $default_product;
+
+ // If all the products are of the same type...
+ if ($same_type) {
+ // Loop through all the field instances on that product type.
+ foreach (field_info_instances('commerce_product', $type) as $name => $instance) {
+ // A field qualifies if it is single value, required and uses a widget
+ // with a definite set of options. For the sake of simplicity, this is
+ // currently restricted to fields defined by the options module.
+ $field = field_info_field($instance['field_name']);
+
+ // Get the array of Cart settings pertaining to this instance.
+ $commerce_cart_settings = commerce_cart_field_instance_attribute_settings($instance);
+
+ // If the instance is of a field type that is eligible to function as
+ // a product attribute field and if its attribute field settings
+ // specify that this functionality is enabled...
+ if (commerce_cart_field_attribute_eligible($field) && $commerce_cart_settings['attribute_field']) {
+ // Get the options properties from the options module and store the
+ // options for the instance in select list format in the array of
+ // qualifying fields.
+ $properties = _options_properties('select', FALSE, TRUE, TRUE);
+
+ // Try to fetch localized names.
+ $allowed_values = NULL;
+
+ // Prepare translated options if using the i18n_field module.
+ if (module_exists('i18n_field')) {
+ if (($translate = i18n_field_type_info($field['type'], 'translate_options'))) {
+ $allowed_values = $translate($field);
+ _options_prepare_options($allowed_values, $properties);
}
- // Otherwise just use the base language values.
- if (empty($allowed_values)) {
- $allowed_values = _options_get_options($field, $instance, $properties);
+ // Translate the field title if set.
+ if (!empty($instance['label'])) {
+ $instance['label'] = i18n_field_translate_property($instance, 'label');
}
+ }
- // Only consider this field a qualifying attribute field if we could
- // derive a set of options for it.
- if (!empty($allowed_values)) {
- $qualifying_fields[$name] = array(
- 'field' => $field,
- 'instance' => $instance,
- 'commerce_cart_settings' => $commerce_cart_settings,
- 'options' => $allowed_values,
- 'weight' => $instance['widget']['weight'],
- 'required' => $instance['required'],
- );
- }
+ // Otherwise just use the base language values.
+ if (empty($allowed_values)) {
+ $allowed_values = _options_get_options($field, $instance, $properties);
+ }
+
+ // Only consider this field a qualifying attribute field if we could
+ // derive a set of options for it.
+ if (!empty($allowed_values)) {
+ $qualifying_fields[$name] = array(
+ 'field' => $field,
+ 'instance' => $instance,
+ 'commerce_cart_settings' => $commerce_cart_settings,
+ 'options' => $allowed_values,
+ 'weight' => $instance['widget']['weight'],
+ 'required' => $instance['required'],
+ );
}
}
}
+ }
- // Otherwise for products of varying types, display a simple select list
- // by product title.
- if (!empty($qualifying_fields)) {
- $used_options = array();
+ // Otherwise for products of varying types, display a simple select list
+ // by product title.
+ if (!empty($qualifying_fields)) {
+ $used_options = array();
- // Sort the fields by weight.
- uasort($qualifying_fields, 'drupal_sort_weight');
+ // Sort the fields by weight.
+ uasort($qualifying_fields, 'drupal_sort_weight');
- foreach ($qualifying_fields as $field_name => $data) {
- // Build an options array of widget options used by referenced products.
- foreach ($products as $product_id => $product) {
- $product_wrapper = entity_metadata_wrapper('commerce_product', $product);
-
- // Only add options to the present array that appear on products that
- // match the default value of the previously added attribute widgets.
- foreach ($used_options as $used_field_name => $unused) {
- // Don't apply this check for the current field being evaluated.
- if ($used_field_name == $field_name) {
- continue;
- }
+ foreach ($qualifying_fields as $field_name => $data) {
+ // Build an options array of widget options used by referenced products.
+ foreach ($products as $product_id => $product) {
+ $product_wrapper = entity_metadata_wrapper('commerce_product', $product);
- if ($product_wrapper->{$used_field_name}->raw() != $form['attributes'][$used_field_name]['#default_value']) {
- continue 2;
- }
+ // Only add options to the present array that appear on products that
+ // match the default value of the previously added attribute widgets.
+ foreach ($used_options as $used_field_name => $unused) {
+ // Don't apply this check for the current field being evaluated.
+ if ($used_field_name == $field_name) {
+ continue;
}
- // With our hard dependency on widgets provided by the Options
- // module, we can make assumptions about where the data is stored.
- $used_options[$field_name][] = $product_wrapper->{$field_name}->raw();
+ if ($product_wrapper->{$used_field_name}->raw() != $form['attributes'][$used_field_name]['#default_value']) {
+ continue 2;
+ }
}
- // If for some reason no options for this field are used, remove it
- // from the qualifying fields array.
- if (empty($used_options[$field_name])) {
- unset($qualifying_fields[$field_name]);
- }
- else {
- $form['attributes'][$field_name] = array(
- '#type' => $data['commerce_cart_settings']['attribute_widget'],
- '#title' => check_plain($data['instance']['label']),
- '#options' => array_intersect_key($data['options'], drupal_map_assoc($used_options[$field_name])),
- '#default_value' => $default_product_wrapper->{$field_name}->raw(),
- '#weight' => $data['instance']['widget']['weight'],
- '#ajax' => array(
- 'callback' => 'commerce_cart_add_to_cart_form_attributes_refresh',
- ),
- );
+ // With our hard dependency on widgets provided by the Options
+ // module, we can make assumptions about where the data is stored.
+ $used_options[$field_name][] = $product_wrapper->{$field_name}->raw();
+ }
- // Add the empty value if the field is not required and products on
- // the form include the empty value.
- if (!$data['required'] && in_array('', $used_options[$field_name])) {
- $form['attributes'][$field_name]['#empty_value'] = '';
- }
+ // If for some reason no options for this field are used, remove it
+ // from the qualifying fields array.
+ if (empty($used_options[$field_name])) {
+ unset($qualifying_fields[$field_name]);
+ }
+ else {
+ $form['attributes'][$field_name] = array(
+ '#type' => $data['commerce_cart_settings']['single_product_display'] ? $data['commerce_cart_settings']['attribute_widget'] : 'hidden',
+ '#title' => check_plain($data['instance']['label']),
+ '#options' => array_intersect_key($data['options'], drupal_map_assoc($used_options[$field_name])),
+ '#default_value' => $default_product_wrapper->{$field_name}->raw(),
+ '#weight' => $data['instance']['widget']['weight'],
+ '#ajax' => array(
+ 'callback' => 'commerce_cart_add_to_cart_form_attributes_refresh',
+ ),
+ );
- $form['unchanged_attributes'][$field_name] = array(
- '#type' => 'value',
- '#value' => $default_product_wrapper->{$field_name}->raw(),
- );
+ // Add the empty value if the field is not required and products on
+ // the form include the empty value.
+ if (!$data['required'] && in_array('', $used_options[$field_name])) {
+ $form['attributes'][$field_name]['#empty_value'] = '';
}
- }
- if (!empty($form['attributes'])) {
- $form['attributes'] += array(
- '#tree' => 'TRUE',
- '#prefix' => '