If you use the Commerce Fancy Attribute module you'll see that your product variations are in a different order than the product attribtues. The solution I'm going to show here is a simple custom code to solve that issue.
The solution is specific to the project and you may be find it useful to create a generic solution too.
/** * Implements hook_element_info_alter(). * * Alter the fancy attributes element. */ function MODULE_NAME_element_info_alter(&$type) { $type['commerce_fancy_attributes']['#process'] = array('MODULE_NAME_fancy_attributes_process_radios'); }
In the element process function we first load the node:
$nid = $form_state['build_info']['args'][2]['entity_id']; $node = node_load($nid);
Then you look up the attributes and product variation delta relationship:
$node_wrapper = entity_metadata_wrapper('node', $node); $products = $node_wrapper->field_product->value(); $attributes = array(); foreach($products as $delta => $product){ if(isset($product->ATTRIBUTE_FIELD) && !empty($product->ATTRIBUTE_FIELD)){ $attributes[$product->ATTRIBUTE_FIELD[LANGUAGE_NONE][0]['target_id']] = $delta; } }
Then you change the fancy attribute weight values for the radio button:
$weight = $attributes[$key];
The complete process function:
/** * Process function for the commerce_fancy_attributes element. * * Each radio button gets a description containing the rendered term. * This description is hidden by default. Then, if JS is enabled, * the radio button and label are hidden, the rendered term in the * description is shown and made clickable. */ function MODULE_NAME_fancy_attributes_process_radios($element, &$form_state, $complete_form = NULL) { if (isset($element['#options']) && count($element['#options']) > 0) { $tids = array_keys($element['#options']); $terms = entity_load('taxonomy_term', $tids); $render_terms = entity_view('taxonomy_term', $terms, 'add_to_cart_form'); $render_terms = $render_terms['taxonomy_term']; $nid = $form_state['build_info']['args'][2]['entity_id']; $node = node_load($nid); $node_wrapper = entity_metadata_wrapper('node', $node); $products = $node_wrapper->field_product->value(); $attributes = array(); foreach($products as $delta => $product){ if(isset($product->ATTRIBUTE_FIELD) && !empty($product->ATTRIBUTE_FIELD)){ $attributes[$product->ATTRIBUTE_FIELD[LANGUAGE_NONE][0]['target_id']] = $delta; } } $weight = 0; foreach ($element['#options'] as $key => $choice) { // Maintain order of options as defined in #options, in case the element // defines custom option sub-elements, but does not define all option // sub-elements. // $weight += 0.001; $weight = $attributes[$key]; $element += array($key => array()); // Generate the parents as the autogenerator does, so we will have a // unique id for each radio button. $parents_for_id = array_merge($element['#parents'], array($key)); // Render only the visible children of the render array, to prevent // unneeded markup. $render = array(); foreach (element_get_visible_children($render_terms[$key]) as $child) { $render[$child] = $render_terms[$key][$child]; } $output = drupal_render($render); $default_value = isset($element['#default_value']) ? $element['#default_value'] : NULL; // Wrap the description with a div specifying the term ID. $class = array('term-' . $key); if ($key == $default_value) { // Add a class specifying this is the currently selected radio. $class[] = 'description-selected'; } $output = '' . $output . ''; $element[$key] += array( '#type' => 'radio', '#title' => $choice, // The key is sanitized in drupal_attributes() during output from the // theme function. '#return_value' => $key, '#default_value' => $default_value, '#attributes' => $element['#attributes'], '#parents' => $element['#parents'], '#id' => drupal_html_id('edit-' . implode('-', $parents_for_id)), '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL, '#weight' => $weight, '#description' => $output, ); } } return $element; }
Comments