0

Can we implement multiple attribute selection sets such as color, size and quantity multiple times for a single product.

Suppose i have a product display that renders 4 products with colors red and blue, sizes XL and L.

So in this case, i can add 4 different selection sets. red-XL-quantity, red-L-quantity, blue-XL-quantity and blue-L-quantity.

Pls check the image for clarification.

enter image description here

I implemented commerce extras with views but it dsnt match my requirement.

I need a link to add multiple sets if necessary.

Thanks :)

  • I used commerce_option module for same purpose. 1 exception in my situation there was one attribute – ar7max Aug 17 '15 at 10:35
  • any clues how to implement this one ?? – Swarnendu Dutta Aug 18 '15 at 12:28
0

I figured this out myself..

So the basic idea is that we build the form based on the setting of $form_state['num_names']. The custom submit functions for the "add more" button increment and decrement $form_state['num_names'] and then force a rebuild of the form. We then iterate over the fields for the product and search for entity reference fields to a commerce option set. (This takes into account that the commerce_product_option module has been properly configured and option sets have been set.) We create a new blank option set each time and add a quantity field with an extra key to attach it with the current option set.

For the submit callback,i had to dig deeper into the module and tweaked a bit for these specific attributes.

<?php

 function multiple_option_sets_form_alter(&$form, &$form_state, $form_id) {
if ((strpos($form_id, 'commerce_cart_add_to_cart_form_') > -1)) {
    multiple_option_sets_add_more_form($form, $form_state, $form_id);
    $form['#submit'][] = 'multiple_option_sets_add_more_submit';
}

}

function multiple_option_sets_add_more_form(&$form, &$form_state, $form_id) {

$form['field_extra_attributes']['#prefix'] = '<div id="ajax-attributes-wrapper">';
$form['field_extra_attributes']['#suffix']= '</div>';


// Build the fieldset with the proper number of names. We'll use
// $form_state['num_names'] to determine the number of textfields to build.
if (empty($form_state['num_names'])) {
    $form_state['num_names'] = 0;
}

for ($i = 0; $i < $form_state['num_names']; $i++) {

    //lets add all the fields we want in the set
    // Because we have many fields with the same values, we have to set
    // #tree to be able to access them.
    $form['#tree'] = TRUE;


    // Get the current product. Is added in the cart module.
    if (isset($form_state['default_product'])) {
        $product_id = $form_state['default_product']->product_id;
    }
    elseif (isset($form_state['default_product_id'])) {
        $product_id = $form_state['default_product_id'];
    }
    elseif (isset($form_state['products'])) {
        $current_product = reset($form_state['products']);
        $product_id = $current_product->product_id;
    }
    else {
        return;
    }

    $current_product = commerce_product_load($product_id);

    $someFieldIsAdded = FALSE;

    // Iterates the fields of this product. We search for entity reference fields
    // to a commerce option set.
    foreach ($current_product as $field_name => $field) {
        $field_info = field_info_field($field_name);

        if ($field_info['type'] != 'entityreference' || !isset($field_info['settings']['target_type']) || $field_info['settings']['target_type'] != 'commerce_option_set') {
            continue;
        }

        // Do not display our options if this field has been marked as an attribute field.
        $field_instance_info = field_info_instance('commerce_product', $field_name, $current_product->type);
        if ($field_instance_info['commerce_cart_settings']['attribute_field']) {
            return;
        }

        $lang_code = field_language('commerce_product', $current_product, $field_name);
        if (!isset($field[$lang_code])) {
            continue;
        }

        // Create a new blank option set.

        foreach($field[$lang_code] as $key => $data) {

            $option_set = commerce_option_set_load($data['target_id']);

            $values = array(
            'set_id' => $option_set->set_id,
            );

            $option = commerce_option_new($values);

            $form_state['commerce_option'][$field_name][$key+1+$i]['option'] = $option;

            $form[$field_name][$key+1+$i] = array(
            '#parents' => array($field_name, $key+1+$i),
            );

            field_attach_form('commerce_option', $option, $form[$field_name][$key+1+$i], $form_state);
            $someFieldIsAdded = TRUE;

        }
    }

    $form['field_extra_attributes'][$i+1]['quantity'] = array(
    '#type' => 'textfield',
    '#title' => t('Quantity'),
    '#prefix' => '<div class="col2">',
    '#suffix' => '</div>'
    );

}

$form['actions']['add_more'] = array(
'#type' => 'submit',
'#value' => t('Add more'),
'#weight' => 50,
'#submit' => array('multiple_option_sets_add_more_add_one'),
'#ajax' => array(
'callback' => 'multiple_option_sets_add_more_callback',
'wrapper' => 'ajax-attributes-wrapper',
),
);

return $form;

}

/**
* Callback for both ajax-enabled buttons. 
*
* Selects and returns the fieldset with the names in it.
*/
function multiple_option_sets_add_more_callback($form, $form_state) {
return $form['field_extra_attributes'];
}

/**
* Submit handler for the "add-one-more" button.
*
* Increments the max counter and causes a rebuild.
*/
function multiple_option_sets_add_more_add_one($form, &$form_state) {
$form_state['num_names']++;
$form_state['rebuild'] = TRUE;
}

/**
* Submit handler for the "remove one" button.
*
* Decrements the max counter and causes a form rebuild.
*/
function multiple_option_sets_add_more_remove_one($form, &$form_state) {
if ($form_state['num_names'] > 1) {
    $form_state['num_names']--;
}
$form_state['rebuild'] = TRUE;
}


function multiple_option_sets_commerce_cart_product_comparison_properties_alter(&$comparison_properties) {
// Force separate line items when the same product is added to the cart from
// different display paths.
$comparison_properties[] = 'field_color';
}

/**
* Cart submit callback function. This is required to create / update
* the option related to the line item.
*
* @param $form Form array
* @param $form_state The form state array.
* @return void
*/
function multiple_option_sets_add_more_submit($form, $form_state){


// Get current product, taking into account different Commerce versions behavior.
if (isset($form_state['default_product'])) {
    $product_id = $form_state['default_product']->product_id;
}
elseif (isset($form_state['default_product_id'])) {
    $product_id = $form_state['default_product_id'];
}
elseif (isset($form_state['products'])) {
    $current_product = reset($form_state['products']);
    $product_id = $current_product->product_id;
}
else {
    return;
}

$current_product = commerce_product_load($product_id);

// Iterates the fields of this product. We search for entity reference fields
// to a commerce option set.
foreach ($current_product as $field_name => $field) {
    $field_info = field_info_field($field_name);

    if ($field_info['type'] != 'entityreference' || !isset($field_info['settings']['target_type']) || $field_info['settings']['target_type'] != 'commerce_option_set') {
        continue;
    }

    $lang_code = field_language('commerce_product', $current_product, $field_name);
    if (!isset($field[$lang_code])) {
        continue;
    }

    foreach ($form_state['values']['field_extra_attributes'] as $delta => $set_id) {

        $option = $form_state['commerce_option'][$field_name][$delta]['option'];

        // Notify field widgets and populate option with values.
        field_attach_submit('commerce_option', $option, $form[$field_name][$delta], $form_state);

        // Check if our option is empty. If yes we shouldn't save anything.
        // Cannot use field_get_items() because it calls field_language().
        $option_extracted = commerce_option_get_valuables($option);
        $ow = entity_metadata_wrapper('commerce_option', $option);
        $empty = TRUE;

        foreach (array_keys($option_extracted) as $option_field) {
            $value = $ow->$option_field->value();
            if (!empty($value)) {
                $empty = FALSE;
                break;
            }
        }

        if ($empty) {
            continue;
        }
        global $user;
        if($delta != 0) {
            $new_line_item = commerce_product_line_item_new($current_product, $form_state['values']['field_extra_attributes'][$delta]['quantity'], $form_state['line_item']->order_id, $form_state['line_item']->data, $form_state['line_item']->type);
            $new_line_item = commerce_cart_product_add($user->uid, $new_line_item);
            //var_dump($form_state['line_item']);
            //var_dump($new_line_item);
            //die();
            $line_item_id = $new_line_item->line_item_id;
        }
        else {
            $line_item_id = $form_state['line_item']->line_item_id;
        }
        $product_id = $current_product->product_id;
        $match = FALSE;

        // Check if the newly created options exist on this line item already.
        // If yes we needn't save anything, commerce will just increase the
        // quantity.
        $query = db_select('commerce_option', 'co')
        ->fields('co', array('option_id'))
        ->condition('line_item_id', $line_item_id, '=')
        ->condition('product_id', $product_id, '=');

        $result = $query->execute()->fetchCol();

        if (!empty($result)) {
            $commerce_option_entities = commerce_option_load_multiple($result);
            $option_extracted = serialize($option_extracted);

            foreach ($commerce_option_entities as $commerce_option) {
                $commerce_option_extracted = commerce_option_get_valuables($commerce_option);
                $commerce_option_extracted = serialize($commerce_option_extracted);
                if ($commerce_option_extracted == $option_extracted) {
                    $match = TRUE;
                    break;
                }
            }
        }

        if ($match) {
            continue;
        }

        $option->line_item_id = $line_item_id;
        $option->product_id = $product_id;

        // Save the option.
        commerce_option_save($option);

    }
}
}
?>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.