Skip to content

\Magento\Quote\Api\CartItemRepositoryInterface::save method doesn't save passed cartItem #5914

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ytorbyk opened this issue Jul 31, 2016 · 8 comments

Comments

@ytorbyk
Copy link
Member

ytorbyk commented Jul 31, 2016

Preconditions

Magento 2.1

Steps to reproduce

  1. Create extension_attribute for \Magento\Quote\Api\Data\CartItemInterface - my_attribute
  2. Create \Magento\Quote\Api\Data\CartItemInterface $cartItem
  3. Assign my_attribute to $cartItem with any value
  4. Pass the $cartItem to \Magento\Quote\Api\CartItemRepositoryInterface::save method

Expected result

  1. The cartItem is added to the cart with all assigned extension_attributes.

Actual result

  1. Only BuyRequest data is taken from the passed $cartItem and is used for creating new instance of \Magento\Quote\Api\Data\CartItemInterface which is added to the cart. (This logic is in \Magento\Quote\Model\Quote\Item\CartItemPersister::save method).

Moreover, if you load existing cartItem, assign an extension_attribute to the cartItem and pass it to the \Magento\Quote\Api\CartItemRepositoryInterface::save method then cartItem will not be updated. Only BuyRequest will be taken from the passed cartItem for updating of exiting cartItem.

Simular problem with product_option of cart item. It's possible to create extension_attributes for product option (or use custom_options) but it is impossible to add your own logic as CartItemProcessor.

@fooman
Copy link
Contributor

fooman commented Aug 15, 2016

I think with extension attributes you need to supply the code yourself to save, store and otherwise process the value. For example take a look at

https://github.com/magento/magento2/blob/2.1.0/app/code/Magento/Bundle/etc/extension_attributes.xml

and then this plugin:

https://github.com/magento/magento2/blob/2.1.0/app/code/Magento/Bundle/Model/Plugin/QuoteItem.php#L31

@ytorbyk
Copy link
Member Author

ytorbyk commented Aug 15, 2016

Yes, I know about this.
As I described in initial topic there is no ability to do that.
You can pass product_option as extended attribute of cart item and custom_options, configurable_item_options or bundle_options as extended attributes of product_option.
Only this data will be taken from the passed cart items and used as BuyRequest data for updating/creating of cart items.
https://github.com/magento/magento2/blob/2.1.0/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php#L69
https://github.com/magento/magento2/blob/2.1.0/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php#L69

All other extended attributes (custom extended attributes) will be lost and there is not ability to save them.

The BuyRequest data is built by CartItemOptionsProcessor. There are hardcoded custom_options processor for all prodcuts and special processors for each type of products (except simple product). There is no ability to specify custom processor.

As solution I used plugin for \Magento\Quote\Model\Quote\Item\CartItemOptionsProcessor and there I process my extended attribute. However I don't think it's a good solution, sure there should be more elegant solution.

@SerhiyShkolyarenko
Copy link
Contributor

SerhiyShkolyarenko commented Sep 8, 2016

Hi Yuriy!
my_attribute value have to be set through setExtensionAttributes() method, but not directly to the quote item object. To check that everything works properly let's modify 2 files in GiftMessage module:

  1. Add the following code to code/Magento/GiftMessage/etc/extension_attributes.xml
    <extension_attributes for="Magento\Quote\Api\Data\CartItemInterface"> <attribute code="my_attribute" type="string" /> </extension_attributes>

  2. Modify constructor and get method of code/Magento/GiftMessage/Model/ItemRepository.php to the state:
    ` public function __construct(
    \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\GiftMessage\Model\GiftMessageManager $giftMessageManager,
    \Magento\GiftMessage\Helper\Message $helper,
    \Magento\Quote\Api\CartItemRepositoryInterface $cartItemRepository,
    \Magento\Quote\Api\Data\CartItemExtensionFactory $cartItemExtensionFactory,
    \Magento\GiftMessage\Model\MessageFactory $messageFactory
    ) {
    $this->quoteRepository = $quoteRepository;
    $this->giftMessageManager = $giftMessageManager;
    $this->storeManager = $storeManager;
    $this->helper = $helper;
    $this->cartItemRepository = $cartItemRepository;
    $this->cartItemExtensionFactory = $cartItemExtensionFactory;
    $this->messageFactory = $messageFactory;
    }

    public function get($cartId, $itemId)
    {
    $quote = $this->quoteRepository->getActive($cartId);
    $quoteItem = $quote->getItemById($itemId);
    $extensionAttributes = $quoteItem->getExtensionAttributes();
    if ($extensionAttributes == null) {
    $extensionAttributes = $this->cartItemExtensionFactory->create();
    }
    $extensionAttributes->setMyAttribute('amazingValue');
    $quoteItem->setExtensionAttributes($extensionAttributes);
    $this->cartItemRepository->save($quoteItem);
    return $quoteItem->getExtensionAttributes()->getMyAttribute();
    }
    `

  3. Clean Magento var/ directory.

  4. Run GET request to /V1/carts/11/gift-message/12 with your cart id and cart item id.

For me this request returned "amazingValue" as expected.
Does it work for you in the same way?

@SerhiyShkolyarenko
Copy link
Contributor

To process the value of extension attribute you need to create plugins to \Magento\Quote\Model\Quote\Item\Repository getList() and save() methods.

@ytorbyk
Copy link
Member Author

ytorbyk commented Sep 8, 2016

Hi thank you for response,
In your example really it works fine.

However, the save method of cart item repository returns saved item and the item doesn't have any extended attributes.
$savedQuoteItem = $this->cartItemRepository->save($quoteItem);
return $savedQuoteItem->getExtensionAttributes(); // null

@ytorbyk
Copy link
Member Author

ytorbyk commented Sep 8, 2016

It looks like the plugin is needed not only for saving extended attributes to DB but even for transferring them from passed quote item to returned quote item.

@ytorbyk
Copy link
Member Author

ytorbyk commented Sep 8, 2016

If it's okay then I'm okay with closing the issue.

@SerhiyShkolyarenko
Copy link
Contributor

$this->cartItemRepository->save() returns another object and some properties will be absent there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants