Order Item Type Resolving Mechanism

Created on 3 December 2018, almost 7 years ago
Updated 13 September 2023, about 2 years ago

Situation

- One catalogue of products (default type) with it's variations (default type)
- Anonymous (role) => default user
- Wholesaler (role) => wholesaler user
- commerce_pricelist module for managing different prices based on context user role (using Calculated Price formatter we already see the different prices for the wholesaler user)
- I need the different checkout experience for the 2 users. Simple (default multistep for guest user), and a customized one with more steps for the wholesaler. I need the different Cart view for them and different cart blocks too.

We need 2 different product types and it's relative variation types as the Add to cart form is actually an "Entity Form" for an Order Item to build. So the parent order may be different himself and the workflows / Carts etc ... may be different. The order item types MAY contain the same prodcut variation type inside, but the product variation (in it's Configuration form [/admin/commerce/config/product-variation-types/%type/edit] has only 1 order item type as reference, while not the other way ... many order item types can reference the same product variation type.

Currently i can't do that with 1 catalogue only, i have to duplicate my products into "wholesale" products that have the "wholesale product variations" that on front-end will generate add to cart form which embeds the entity of type "Wholesale order item" (not the default one).

Now, that being said ... this small diagram that shows the current state of art:


Hack solution 1

Add a form alter HOOK, that drops all the add_to_cart_form::submitForm() actions and manually creates the "wholesaler" order item (as a child of order type "wholesaler") copying the info from the form_state prepared for the "default" order item. Stop ... after that .. i suppose the rest is out-of-the-box functionality.

Hack solution 2

Actually there's more elegant solution (but still hacky): The commerce/modules/product actually defines a FieldFormatter AddToCartFormatter for the productVariations inside product display. And this guy uses a lazy builder for building the actual form:

  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];
    $elements[0]['add_to_cart_form'] = [
      '#lazy_builder' => [
        'commerce_product.lazy_builders:addToCartForm', [
          $items->getEntity()->id(),
          $this->viewMode,
          $this->getSetting('combine'),
          $langcode,
        ],
      ],
      '#create_placeholder' => TRUE,
    ];
    return $elements;
  }

So basically we could alter the service for this lazy builder with our own and do whatever we want.

Hack solution 3 (by @mgalman)

With a simple HOOK_entity_type_build we can alter the Class that comands the add to cart form. Which is actually is a entity form for commerce_order_item bundle content entity.

/**
* Implements hook_entity_type_build().
*/
function mymodule_entity_type_build(array &$entity_types) {
  $entity_types['commerce_order_item']->setFormClass('add_to_cart', '\Drupal\mymodule\Form\CustomAddToCartForm');
}

Then alter the logics of the add to cart form as you wish.

Proposed solution

We need a some kind of Order Item Type Resolver

Something like this...


The basic patch is included.

Feature request
Status

RTBC

Version

2.0

Component

Line item

Created by

🇮🇹Italy eglaw Cittadella

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇩🇪Germany Anybody Porta Westfalica

    This still blocks https://www.drupal.org/project/commerce_pvt

    So is there any plan to merge this finally?

    @mglaman is still self-assigned.

  • 🇮🇹Italy eglaw Cittadella

    @Anybody if i only knew ... the only things they've told me is that basically this mechanism adds complications on a simple thing, and it probably doesn't fit into basic commerce usage.

  • Issue was unassigned.
  • 🇺🇸United States mglaman WI, USA

    removing myself

  • 🇩🇪Germany Anybody Porta Westfalica

    @mglaman is an official statement possible here perhaps? So the community at least knows what's going to happen! Looks like a lot of time and brain went into this, so would be sad to let it die like this...

  • Status changed to Needs review 10 months ago
  • 🇩🇪Germany Anybody Porta Westfalica

    Please re-evaluate against 3.0.x. 2 years after RTBC quite unclear how to proceed with this? Also see #53 + #54

  • 🇮🇹Italy eglaw Cittadella

    @anybody
    I will check and update as soon as commerce 3.x stable will roll out.

  • 🇩🇪Germany geek-merlin Freiburg, Germany

    Maybe a better IS helps.

  • 🇺🇸United States mradcliffe USA

    I think this is still relevant because hack Solution #3 which is in commerce_cart.module seems to be broken for me in Commerce 3.0.2 (3.1.0 not tried).

    The Entity Type definition is being cached without the add_to_cart form handler and this causes EntityTypeManager via ProductLazyBuilders to throw an exception. Flushing the cache completely will resolve the issue temporarily, but it seems there are times when the Entity Type definition cache is built without calling hook_entity_type_build or a race condition might be causing it not to get called in time? The site is not using any memory cache, only database cache.

    Stack trace:

    Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "commerce_order_item" entity type did not specify a "add_to_cart" form class. in Drupal\Core\Entity\EntityTypeManager->getFormObject() (line 212 of core/lib/Drupal/Core/Entity/EntityTypeManager.php).
    
    Drupal\commerce_product\ProductLazyBuilders->addToCartForm()
    

    So an improved Order Item Type resolver would be better.

  • 🇺🇸United States mradcliffe USA

    Th exceptions are due to 🐛 ModuleHandler skips all hook implementations when invoked before the module files have been loaded Needs review which makes using hook_entity_type_build unreliable currently.

Production build 0.71.5 2024