Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento change Custom Option value before adding it to cart

Tags:

magento

I have setup a custom option for my product in Magento as dropdown i.e.

Size : Small, Medium, Large

On product page I show additional information for each option using javascript.

Small - Waist 30, Chest 36, Length 42...
Medium - Waist 32, Chest 38, Length 44...
Large - Waist 34, Chest 40, Length 48...

When I add product to cart i get the Size title (Small, Medium or Large) in cart but I also want to show this additional information (Waist 30, Chest 36, Length 42...) and get it saved with order.

What is best way to do it? Thanks in advance.

like image 648
Farrukh Avatar asked Feb 17 '12 19:02

Farrukh


1 Answers

The custom options are only stored on the quote as option ID's and values. Every time the options are rendered, they are basically reloaded from the database.
If you modify the values, you would need to save them, and that would set them for everybody.

That said, I work around the issue by adding an additional custom option with the modified value on the fly, using an event observer. For this I use additional options.
Then I remove the original custom option from the quote item.

Up to 1.4 Magento took care of the rest, but since then you need to copy the additional options to the order item manually, and also need to take care it's set again if an item is reordered.

So here is an example observer configuration.

<frontend>
    <events>
        <checkout_cart_product_add_after>
            <observers>
                <customoptions>
                    <type>singleton</type>
                    <class>customoptions/observer</class>
                    <method>checkoutCartProductAddAfter</method>
                </customoptions>
            </observers>
        </checkout_cart_product_add_after>
        <sales_convert_quote_item_to_order_item>
            <observers>
                <customoptions>
                    <type>singleton</type>
                    <class>customoptions/observer</class>
                    <method>salesConvertQuoteItemToOrderItem</method>
                </customoptions>
            </observers>
        </sales_convert_quote_item_to_order_item>
    </events>
</frontend>

The rest is handled in the observer class.

/**
 * Add additional options to order item product options (this is missing in the core)
 *
 * @param Varien_Event_Observer $observer
 */
public function salesConvertQuoteItemToOrderItem(Varien_Event_Observer $observer)
{
    $quoteItem = $observer->getItem();
    if ($additionalOptions = $quoteItem->getOptionByCode('additional_options')) {
        $orderItem = $observer->getOrderItem();
        $options = $orderItem->getProductOptions();
        $options['additional_options'] = unserialize($additionalOptions->getValue());
        $orderItem->setProductOptions($options);
    }
}

/**
 * Manipulate the custom product options
 *
 * @param Varien_Event_Observer $observer
 * @return void
 */
public function checkoutCartProductAddAfter(Varien_Event_Observer $observer)
{
    $item = $observer->getQuoteItem();
    $infoArr = array();

    if ($info = $item->getProduct()->getCustomOption('info_buyRequest')) {
        $infoArr = unserialize($info->getValue());
    }

    // Set additional options in case of a reorder
    if ($infoArr && isset($infoArr['additional_options'])) {
        // An additional options array is set on the buy request - this is a reorder
        $item->addOption(array(
            'code' => 'additional_options',
            'value' => serialize($infoArr['additional_options'])
        ));
        return;
    }

    $options = Mage::helper('catalog/product_configuration')->getCustomOptions($item);

    foreach ($options as $option)
    {
        // The only way to identify a custom option without
        // hardcoding ID's is the label :-(
        // But manipulating options this way is hackish anyway
        if ('Size' === $option['label'])
        {
            $optId = $option['option_id'];

            // Add replacement custom option with modified value
            $additionalOptions = array(array(
                'code' => 'my_code',
                'label' => $option['label'],
                'value' => $option['value'] . ' YOUR EXTRA TEXT',
                'print_value' => $option['print_value'] . ' YOUR EXTRA TEXT',
            ));
            $item->addOption(array(
                'code' => 'additional_options',
                'value' => serialize($additionalOptions),
            ));

            // Update info_buyRequest to reflect changes
            if ($infoArr &&
                isset($infoArr['options']) &&
                isset($infoArr['options'][$optId]))
               {
                // Remove real custom option
                unset($infoArr['options'][$optId]);

                // Add replacement additional option for reorder (see above)
                $infoArr['additional_options'] = $additionalOptions;

                $info->setValue(serialize($infoArr));
                $item->addOption($info);
            }

            // Remove real custom option id from option_ids list
            if ($optionIdsOption = $item->getProduct()->getCustomOption('option_ids')) {
                $optionIds = explode(',', $optionIdsOption->getValue());
                if (false !== ($idx = array_search($optId, $optionIds))) {
                    unset($optionIds[$idx]);
                    $optionIdsOption->setValue(implode(',', $optionIds));
                    $item->addOption($optionIdsOption);
                }
            }

            // Remove real custom option
            $item->removeOption('option_' . $optId);
        }
    }

This is it in a nutshell. Add error checking and taking care of special cases like adding the same product to the cart again as needed.
Hope this gets you started working with custom product options. Not half bad once you get familiar with them.

like image 171
Vinai Avatar answered Nov 07 '22 17:11

Vinai