function _commerce_cart_matching_products in Commerce Core 7
Returns an array of products matching a set of attribute values.
Parameters
$products: An array of product objects.
$form_state: The $form_state from an Add to Cart form.
1 call to _commerce_cart_matching_products()
- commerce_cart_add_to_cart_form in modules/
cart/ commerce_cart.module - Builds an Add to Cart form for a set of products.
File
- modules/
cart/ commerce_cart.module, line 1733 - Implements the shopping cart system and add to cart features.
Code
function _commerce_cart_matching_products($products, &$form_state) {
$matching_products = array();
// If the form state contains attribute data...
if (!empty($form_state['values']['attributes'])) {
$changed_attribute = NULL;
$attributes = (array) array_diff_key($form_state['values']['attributes'], array(
'product_select' => '',
));
$unchanged_attributes = $form_state['values']['unchanged_attributes'];
// Get the changed attribute.
foreach ($attributes as $attribute_name => $attribute_value) {
// If this is the attribute widget that was changed...
if ($attribute_value != $unchanged_attributes[$attribute_name]) {
// Store the field name.
$changed_attribute = $attribute_name;
// Clear the input for the "Select a product" widget now if it
// exists on the form since we know an attribute was changed.
unset($form_state['input']['attributes']['product_select']);
// We found the changed attribute so we're done.
break;
}
}
// If we found a changed attribute and it's not already in the first
// position of the array.
if (!empty($changed_attribute) && array_search($changed_attribute, array_keys($attributes))) {
// Move the changed attribute to the first position of the array so it's
// handled first.
$attributes = array(
$changed_attribute => $attributes[$changed_attribute],
) + $attributes;
}
// Create a list of all products associated with each attribute for
// filtering.
$attributes_products = array_fill_keys(array_keys($attributes), array());
foreach ($products as $product_id => $product) {
// Store which attributes this product is associated with.
foreach ($attributes as $attribute_name => $attribute_value) {
$product_attribute_items = field_get_items('commerce_product', $product, $attribute_name);
$product_attribute_value = reset($product_attribute_items[0]);
if ($product_attribute_value == $attribute_value) {
$attributes_products[$attribute_name][$product_id] = $product;
}
}
}
// Filter out products starting with those not associated with the changed
// attribute and proceeding with those not associated with other attributes
// in the order the attributes appear in the form.
$matching_products = array_shift($attributes_products);
foreach ($attributes_products as $attribute_name => $attribute_products) {
$filtered_products = array_intersect_key($matching_products, $attribute_products);
// If all products have been filtered out, use the set of products prior
// to filtering on the current attribute.
if (!empty($filtered_products)) {
$matching_products = $filtered_products;
}
else {
break;
}
}
// Only accept the first matching product and subsequent matching products
// with identical attribute values.
if (count($matching_products) > 1) {
$default_product = reset($matching_products);
unset($matching_products[key($matching_products)]);
$default_products[$default_product->product_id] = $default_product;
foreach ($matching_products as $matching_product_id => $matching_product) {
foreach ($attributes as $attribute_name => $attribute_value) {
$matching_product_attribute_items = field_get_items('commerce_product', $matching_product, $attribute_name);
$matching_product_attribute_value = reset($matching_product_attribute_items[0]);
$default_product_attribute_items = field_get_items('commerce_product', $default_product, $attribute_name);
$default_product_attribute_value = reset($default_product_attribute_items[0]);
if ($matching_product_attribute_value != $default_product_attribute_value) {
continue 2;
}
}
$default_products[$matching_product_id] = $matching_product;
}
$matching_products = $default_products;
}
}
return $matching_products;
}