Problem/Motivation

The cart provider defines several methods for getting carts:

  • getCartId()
  • getCart()
  • getCartIds()
  • getCarts()

For whatever reason, it is only possible to specify the store, for the "singular" methods (i.e for retrieving a single cart), but there's no way to restrict the carts collection by store.

Additionally, the query performed by loadCartData() should always have a "store_id" condition, and if no store is provided, we should default to the current store to match what's currently done in getCartId()/getCart().

Comments

jsacksick created an issue. See original summary.

jsacksick’s picture

Issue summary: View changes
jsacksick’s picture

Status: Active » Needs review
StatusFileSize
new7.15 KB

Tests need to be expanded, and we probably need a change record, attaching a patch to validate the approach first.

jsacksick’s picture

Issue summary: View changes
jsacksick’s picture

Issue summary: View changes
jsacksick’s picture

StatusFileSize
new7.81 KB
new1.05 KB
jsacksick’s picture

StatusFileSize
new11.01 KB
new4 KB
jsacksick’s picture

Title: The cart provider should return carts for the current store » Improvements to the CartProvider
jsacksick’s picture

StatusFileSize
new11.49 KB
new3.06 KB
jsacksick’s picture

rszrama’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new11.93 KB

Only thing missing was a documentation update for CartProvider::cartData. Only bummer about the patch is the inconsistency in ordering of the store vs. account parameters, but I understand our hands are tied on CartProvider::createCart() to preserve BC. 😬

Patch attached updates the property docs at the top, should still commit fine - no other code was changed. fwiw, in my single store site, this obviously works as expected. I haven't tried it in a multi-store setup but don't see why it shouldn't work.

jsacksick’s picture

Only bummer about the patch is the inconsistency in ordering of the store vs. account parameters, but I understand our hands are tied on CartProvider::createCart() to preserve BC. 😬

Yeah, I agree, but there's no way we can change this now unfortunately!

Thank you for the documentation update!

I'm still wondering whether we should default to the current store in loadCartData() (instead of not applying the store filter if no store is passed), because any implementation calling getCarts() would now only get carts for the current store (if no store is passed), instead of getting carts for all stores...

Do you think that's a valid concern?

mglaman’s picture

I think anyone with multistore is a small portion of users. And those who have used multiple stores use them across domains. So this change improves their experience - developer and QA creating carts between domains locally.

We can pop a change record and anyone with custom code and understand why

  • jsacksick committed fad34ca on 8.x-2.x
    Issue #3179466 by jsacksick, mglaman, rszrama: Improvements to the...
jsacksick’s picture

Status: Reviewed & tested by the community » Fixed

Committed! Thanks everyone :).

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

krystalcode’s picture

I think anyone with multistore is a small portion of users. And those who have used multiple stores use them across domains.

Some assumptions here. It's ok that you make such decisions and changes, however, could you at least be highlighting them in the release notes when you introduce backward-breaking changes? Make the life of developers easier when updating.

ocastle’s picture

I'd agree with @krystalcode.

This also breaks modules like commerce_api and commerce_marketplace and there is now no way of requesting all carts for a single user.

I understand the idea to 'improve' the cart provider, but this changes its functionality for no real reason, significantly reducing its flexibility.

We should have at least added additional methods such as getAllCarts and getAllCartIds and move the default fallback store outside of loadCartData to keep some flexibility.

krystalcode’s picture

If anybody relies on the previous behavior, I will be fixing the regression on Commerce Cart Advanced where I'll be keeping the previous behavior i.e. return all carts unless a specific store is explicitly requested.

jsacksick’s picture

@ocastle, @krystalcode: I concede that a change like this would have deserve a change record at the very least.

It's also true that the issue title / summary doesn't properly describe what was done and why...

While we probably fixed issues occurring in a multi store / multi domain setup... We probably neglected the side effects for the marketplace usecase...

I'm wondering how we can satisfy all of the use cases properly and whether there's a way to partially revert some of the changes introduced here.

What I would like to get is proper bug reports that describe the expected behavior and the bug encountered so I can do something about it...

Thus far, 2 issues were created (#3193126: Unable to place an order which is very confusing and #3184614: Multi-Cart NOT supported: products from secondary stores are NOT displayed which doesn't clearly describe the issue either...

DId we break only the /cart page, or is there more than that?

@ocastle: could you help with filling a proper bug report / updating the existing one?

krystalcode’s picture

@jsacksick

I think the best is that caller of the cart provider should be deciding which carts to fetch rather than the provider deciding internally. That is the cart view, for example, should have a way to say give me only the carts for this store or all carts. I can create an issue with a proposal later when I can.

ocastle’s picture

@krystalcode let me know if you need some additional information for the issue. happy to help.

bojanz’s picture

Status: Closed (fixed) » Needs work

Let's reopen this issue.

Additionally, the query performed by loadCartData() should always have a "store_id" condition, and if no store is provided, we should default to the current store to match what's currently done in getCartId()/getCart().

This is a major BC break and needs to be reverted. It basically removes the ability to list carts belonging to multiple stores.

krystalcode’s picture

Ok, let's keep it here.

I've thought a bit about this and I don't think we actually need a new solution, we just need the previous behavior.

- If a site has only one store, then there's no problem, all carts will be loaded and they are all from the same store.
- If a site is a multi-domain site, it could be handy to default to the current store as that would be determined by the current domain, but then there must be custom code or through contrib to associate each store with a domain and I feel that whoever is providing that should be responsible for customizing the cart controller to their needs. There could even be multi-domain sites with multiple stores per domain, let them deal with that as they need.
- If a site is a marketplace i.e. multiple stores, then it's actually desired to have carts from multiple stores displayed.

I think we can keep the ability to provide a specific store, even though that requires other modules that extend the cart provider to be updated - that's ok. And just load all carts if no specific store was requested.

jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new11.89 KB

The main problem with the "old" behavior is that it isn't really consistent.
getCart() and getCartId() both accept an optional $store parameter, but not getCarts() and getCartIds().

Now that we've introduced this extra $store parameter to getCarts() and getCartIds() I think we should still keep that... But then obviously we can't default to the current store since that'd be similar to keeping the store_id condition in loadCartData().

Is it ok to be inconsistent and not default to the current store there?

Now, regarding the actual issue we were attempting to address in the first place, modifying the cart provider was probably not the right approach.
An alternative solution would be to add a contextual store filter to the cart view that defaults to the current store...

Note that we could also somehow introduce a setting that we'd rely on in the cart controller that determines whether or not we should pass the current store to getCarts().

The attached patch partially reverts the commit (We still can optionally pass a store to getCartIds() and getCarts() but it no longer defaults to the current store. (loadCartData() doesn't filter on the store anymore.

jsacksick’s picture

StatusFileSize
new12.67 KB
new4.96 KB

The attached patch fixes phpcs violations, and also update the test to remove the unnecessary store type + store creation since we already have a store available.

zenimagine’s picture

@jsacksick I just tested the patch but I don't have the behavior before the last update at all. I have a marketplace and if I add products from 2 different stores, it will create a single shopping cart.

Before it work properly and it create 2 shopping carts.

I have the Drupal Commerce and Commerce Markerplace modules.

I hope that Drupal Commerce can finally manage marketplaces properly.

jsacksick’s picture

Well then maybe it's due to another change, and not the patch from here...

Wondering if somehow, the change from #3143382: AddToCartForm should reference the destination cart when building the order item is affecting this.

I hope that Drupal Commerce can finally manage marketplaces properly.

A marketplace can be implemented very differently depending on the use-case... It isn't our main focus and it'll be the responsibility of the Commerce marketplace module to implement it as required to satisfy the usecase addressed by the module.

On the Commerce core side we should ensure this is possible, but we'll never implement the marketplace usecase directly in core.

rszrama’s picture

Created #3193580-3: Add a cart settings form to filter the cart page to the current store as a follow-up issue to reenact the behavior we were trying to prioritize, which is the more clear use case of a multi-store site where 1 store = 1 domain and carts should not be visible off-domain.

ocastle’s picture

Patch #26 fixes the issue for me and restores the ability to load all users carts at once.

I believe it still adds the functionality that this issue was trying to solve, but i'm not in a position to confirm this.

zenimagine’s picture

@ocastle Is the patch working for you ? I tested it and it does not allow you to create multiple shopping carts. If I add products from multiple stores, I only have one shopping cart. It should display a shopping cart by store. Do you use Commerce Marketplace ?

jsacksick’s picture

@zenimagine: I doubt this change is related.. This allows getting carts from multiple stores again, without defaulting to the current store. Have you tried reverting the other change I linked?

  • jsacksick committed 285560c on 8.x-2.x
    Issue #3179466 followup: Ensure CartProvider::getCarts() supports...
jsacksick’s picture

Status: Needs review » Fixed

Committed the patch from #26, thanks for the feedbacks/testing.

ocastle’s picture

@zenimagine The patch restored the original setup on cart provider which mainly affected my commerce_api implementation.

I do use commerce marketplace but not the UI and I know the result you're expecting, but agree with @jsacksick, not sure this patch would have changed that. Might be worth opening issue on commerce_marketplace?

londova’s picture

Yes, it works,
I have separate cart for each store as it was previously.
Thank You.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.