This is something the D7 commerce_order_types module had, and it makes sense. Some order types shouldn't be carts, because a site will send the user directly to checkout (or perform the checkout directly on the product page). Trainings, for example.

How to use the patch (from #126 on)

1. Apply the patch.
2. Go to the order types admin screen: /admin/commerce/config/order-types/
3. Click edit on the order type that you want to enable direct checkout.
4. Check the box for direct checkout at the bottom of the edit screen.
5. Save.

CommentFileSizeAuthor
#180 interdiff_178_180.txt2.4 KBtBKoT
#180 2810723-180.patch15.45 KBtBKoT
#178 interdiff_177_178.txt1.19 KBtBKoT
#178 2810723-178.patch15.47 KBtBKoT
#177 interdiff_175_177.txt7.09 KBtBKoT
#177 2810723-177.patch14.71 KBtBKoT
#175 interdiff_170_175.txt17.15 KBtBKoT
#175 2810723-175.patch13.3 KBtBKoT
#174 interdiff_170_174.txt17.15 KBtBKoT
#174 2810723-174.patch13.32 KBtBKoT
#172 cart-redirect-select.png18.65 KBjsacksick
#172 cart-redirect-checkbox.png11.16 KBjsacksick
#170 interdiff_160_170.txt10.32 KBtBKoT
#170 2810723-170.patch6.96 KBtBKoT
#160 interdiff_156-160.patch1.01 KBcoffeemakr
#160 2810723-160.patch11.07 KBcoffeemakr
#156 interdiff_155-156.patch3.71 KBcoffeemakr
#156 2810723-156.patch11.07 KBcoffeemakr
#155 2810723-155.patch11.61 KBYasser Samman
#154 2810723-154.patch11.65 KBYasser Samman
#152 allow-order-types-to-have-no-carts-2810723-152.patch11.65 KBbalis_m
#141 0001-Reroll.patch12.29 KBscotthooker
#140 2810723.patch12.29 KBscotthooker
#131 interdiff_126-130.txt1.4 KBvalic
#130 interdiff_126-130.txt1.4 KBvalic
#130 2810723-130.patch11.5 KBvalic
#126 interdiff_125-126.txt1.03 KBvalic
#126 2810723-126.patch11.48 KBvalic
#125 interdiff_123-125.txt13.39 KBvalic
#125 2810723-125.patch11.58 KBvalic
#123 interdiff_122-123.txt11 KBvalic
#123 2810723-123.patch14.23 KBvalic
#122 interdiff_118-122.txt872 bytesvalic
#122 2810723-122.patch13.97 KBvalic
#119 interdiff_106-118.txt1.16 KBvalic
#119 2810723-118.patch13.23 KBvalic
#116 interdiff-107-116.txt22.97 KBvalic
#116 2810723-116.patch13.21 KBvalic
#107 interdiff.txt1.85 KBjoelpittet
#107 2810723-107-direct-checkout.patch12.62 KBjoelpittet
#102 interdiff-98-102.txt767 bytespiggito
#102 commerce-direct_checkout-2810723-102.patch13.22 KBpiggito
#98 commerce-direct_checkout-2810723-98.patch13.21 KBfloydm
#98 interdiff-92-98.txt2.17 KBfloydm
#92 commerce-direct_checkout-2810723-92.patch12.88 KBbaikho
#87 2810723-87-reroll-69-direct-checkout.patch12.82 KBjoelpittet
#81 2810723-81.patch12.81 KBlawxen
#69 commerce-direct-checkout-69.patch12.61 KBElusiveMind
#68 commerce-direct-checkout-68.patch12.6 KBElusiveMind
#63 commerce-direct-checkout-63.patch12.61 KBwilleaton
#50 commerce-direct-checkout-50.patch12.59 KBMaxime Gilbert
#49 commerce-direct-checkout-49.patch12.6 KBMaxime Gilbert
#48 commerce-direct-checkout-48.patch12.59 KBMaxime Gilbert
#45 commerce-direct-checkout-45.patch12.57 KBMaxime Gilbert
#40 commerce-direct-checkout-40.patch11.98 KBxSDx
#37 commerce-direct-checkout-2.2-2810723-37.patch12.74 KBptmkenny
#36 commerce-direct-checkout-2.2-2810723-36.patch16.1 KBptmkenny
#27 commerce-direct-checkout-2.0-2810723-27.patch12.74 KBptmkenny
#26 commerce-direct-checkout-2.0-2810723-26.patch12.94 KBptmkenny
#23 commerce-direct-checkout-beta7-2810723-23.patch13.06 KBBerdir

Issue fork commerce-2810723

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bojanz created an issue. See original summary.

Londova’s picture

Sounds good.
We need such for selling "virtual goods", where is a single line per order.

scotthooker’s picture

Looking into this a bit more. I guess the start would be to supply a new version of the add to cart form.

bojanz’s picture

We would need a setting on the order type.
The cart provider would not provide carts of that type (this might break a few things).
The add to cart form would check the setting, and rename the submit button to Checkout instead of Add to cart, go to checkout directly.

scotthooker’s picture

- this is a contrib solution - https://github.com/scotthooker/commerce_checkout_direct

I'll take a look at your suggestions for it in core.

In addition it would need to not display an item added to cart message.

mglaman’s picture

So one problem

rename the submit button to Checkout instead of Add to cart, go to checkout directly.

Do we only show this setting, this modification, if commerce_checkout is enabled?

EDIT: IMO this is kind of squirrely. I'd almost rather defer to https://github.com/scotthooker/commerce_checkout_direct which can be used out of the box by pointing a variation type to that order item type and "it just works", or it at least provides sample code. It's something I wrote then handed to scotthooker which he graciously packaged up nicely :)

bojanz’s picture

The linked module doesn't resolve the main issue, which is that you simply don't want to have a cart in certain cases (whatever is bought in one go, trainings, donations, etc).

Plus, we definitely need such behavior to be attachable to existing order types, you can't force people to use a single order type just to get this.

scotthooker’s picture

"The linked module doesn't resolve the main issue, which is that you simply don't want to have a cart in certain cases (whatever is bought in one go, trainings, donations, etc).

Plus, we definitely need such behavior to be attachable to existing order types, you can't force people to use a single order type just to get this."

Absolutely - I could hear you saying that as I wrote they YML for the order type. Its entirely restrictive and removes the flexibility of having multiple order types. It wants to be an option on the order type so its generic.

HOWEVER, this will do for now and keep this feature request ticket open whilst I look at a more generic solution.

scotthooker’s picture

mglaman’s picture

The more I think about this, it's more of a contrib module. We need something which adds third party settings to an order type and allows it to skip carts. At the same time, it could provide a "direct to checkout" form alongside the event subscriber.

We need a "bridge" module which is aware of Cart and Checkout, without actually coupling those two together in core, I feel like.

scotthooker’s picture

Just feels a bit out of place to have to install contrib to skip over a feature of core. I want to skip the checkout. Should be do-able from core?

bojanz’s picture

I have no doubt that this feature should be in core.
I've used the equivalent commerce_order_types feature in several D7 projects.

I'll try to figure out a clean way for this once shipping is done (so, february most likely)

scotthooker’s picture

Happy to review when you have sir.

mglaman’s picture

Commerce product owns nearly all the components we need. What if Checkout provided its own form like add to Cart that went straight to checkout?

JMOmandown’s picture

I think it's important to be able to remove the cart module all together under this scenario which would mean varying away from the standard add to cart button and overwriting or resetting the defined route to get to the checkout page directly. With that said, it almost makes sense based on the comments to move towards what used to be the old add to cart by url module. I would do something like the following to give the most flexibility to the end user:

https://www.drupal.org/sandbox/jmomandown/2844445

Note this was put together rather quickly and is not up to standards nor full featured.

mglaman’s picture

I think the proper approach isn't an order type setting, but something of a direct to checkout button, provided by the checkout module.

The direct to checkout would add the current item to a new order, with specified quantity and bring them immediately to checkout. There'd be no cart, combining of order items, etc. Just make a new order and bring them to checkout to finish purchasing what they selected. This would be a new formatter, like the add to cart formatter. It'd help provide a similar "one click purchase" that Amazon provides.

Berdir’s picture

Assigned: Unassigned » Berdir

Going to give this a try. I'll start with adding an option to the existing formatter/form then, the alternative is to copy/extend/refactor the formatter, lazy builder service and form. While that makes sense, e.g. to get rid of the cart dependency, checkout right now actually depends on cart anyway, so it's not like you can have a checkout and not install the cart module at all.

Berdir’s picture

Assigned: Berdir » Unassigned
Status: Active » Needs review

Some things I noticed while working on this:

* not sure if a static to ensure a unique form ID is reliably (what if a new product is added to a list between displaying and submitting a form?), but also not sure about a better alternative, so far I only had to deal with pre-configured multiple forms like blocks. Maybe product id + settings or so, even if that would exist multiple times on a page it wouldn't matter as it actually would be the same form then.

* the settings summary for combine is pretty long, often that's not full sentences but just keywords.

* the combine setting doesn't make sense with direct checkout as it is guaranteed to be a new order that doesn't have anything in it yet.

* AddToCartForm obviously makes no sense for a form/formatter that doesn't add something to cart. but we can still refactor things.

* The standard question when not using cart is how to deal with access for anonymous users, related to #2824320: Checkout access is incomplete commerce 1.x now has a hook for this I think to be more flexible but then we probably need to store this in a separate session key or support a allowed-access-but-not-cart default session key.

All those things aside, doing this with a formatter setting is pretty trivial, at least for authenticated users. For anonymous users, this currently results in an access denied after clicking the button.

Will work on tests tomorrow hopefully. Or rework it when I get feedback to got with a different approach.

https://github.com/drupalcommerce/commerce/pull/669

Berdir’s picture

https://github.com/drupalcommerce/commerce/pull/669 is now passing.

I added tests for authenticated and anon users. Anon users currently works with a similar trick that I often used in projects in 7.x, I added the order id to as a *completed* cart.

As commented in IRC, dependencies are tricky, as the formatter now really requires commerce_checkout and cart does not (can't because checkout requires cart), I had to add commerce_checkout to the cart browse tests.

There are still various issues and it is a bit messy, but it seems to work quite well, so I think ready for a review.

dubcanada’s picture

What about if you don't want to go to the checkout page?

Say you want to use the order types for something that should never be able to checkout (example wishlist or something).

bojanz’s picture

@dubcanada
Wishlists should be their own entities (in fact, commerce_wishlist already implements its own entity type).
Entities are quick & cheap in D8 and there's no reason to hijack existing entity types.

dubcanada’s picture

Okay.

Is there any use case where a user would not want to be sent to the checkout form? If not I reviewed #19 and it does what it says it does.

Berdir’s picture

Patch against beta7 if someone needs that.

PR has some test fails but a review of the general approach would be great before I focus on fixing the tests.

smaz’s picture

With this approach:

* What happens if the user then visits /cart? It appears they'd still be able to view their cart, correct?

* What happens if the user adds a second item to their cart?, i.e. goes from checkout back to the store
@scotthooker took care of that with his module:
https://github.com/scotthooker/commerce_checkout_direct/blob/master/src/...
Thinking of the use case of buying one of a set of options, like a subscription (1 month, 3 month, 12 month etc), or web hosting packages & so on.

* What happens for carts that don't use products?
Not sure this is in scope / up for consideration yet, but it's possible. https://www.drupal.org/node/2853280

Berdir’s picture

This currently does one simple thing. It creates a new order, creates an order item in there for the product and goes to checkout.

* Multiple products isn't supported
* it doesn't do anything about /cart
* Non-product order items isn't relevant because this is a product formatter, so there is a product.

ptmkenny’s picture

I re-rolled the patch for 2.0, but after applying, when I try to add a product to a cart, I get:

Drupal\Core\Entity\EntityStorageException: Missing bundle for entity type commerce_order in Drupal\Core\Entity\ContentEntityStorageBase->doCreate() (line 83 of core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php).

I'm guessing this is related to these notices:

Notice: Undefined variable: order_type ( /app/web/modules/contrib/commerce/modules/cart/src/Form/AddToCartForm.php の 241 行目 Drupal\commerce_cart\Form\AddToCartForm->submitForm() 内)
Notice: Undefined variable: order_type ( /app/web/modules/contrib/commerce/modules/cart/src/Form/AddToCartForm.php の 243 行目 Drupal\commerce_cart\Form\AddToCartForm->submitForm() 内)
ptmkenny’s picture

FileSize
12.74 KB

Ok, here is a working patch for Commerce 2.0.

Minor changes I had to make to Berdir's patch:

$order_type is now $order_type_id.

drupal_set_message() is no longer used to show the "cart added" message, so that part can be deleted.

How to use this feature (reminder to myself)

1. Apply this patch.
2. Go to the Product Types -> Edit Display page for your product type that you want to skip the cart for (/admin/commerce/config/product-types/my-product-type/edit/display).
3. Look for the "Product Variations" field, the format of which should be "Add to cart" form. Click the little gear icon on the right.
4. Check the box for "Skip cart" and press "Update".

sorabh.v6’s picture

Assigned: Unassigned » sorabh.v6
sorabh.v6’s picture

Assigned: sorabh.v6 » Unassigned
sorabh.v6’s picture

Assigned: Unassigned » sorabh.v6
mglaman’s picture

Status: Needs review » Needs work
  1. +++ b/modules/cart/src/Form/AddToCartForm.php
    @@ -201,13 +213,38 @@ class AddToCartForm extends ContentEntityForm implements AddToCartFormInterface
    +      // Create the new order.
    +      /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    +      $order = $this->entityTypeManager->getStorage('commerce_order')->create([
    +        'type' => $order_type_id,
    +        'store_id' => $store->id(),
    +        'uid' => $this->currentUser()->id(),
    +        'cart' => FALSE,
    +      ]);
    

    This should still use the cart provider. Cart should be true, so that checkout works.

  2. +++ b/modules/cart/src/Form/AddToCartForm.php
    @@ -201,13 +213,38 @@ class AddToCartForm extends ContentEntityForm implements AddToCartFormInterface
    +      $this->cartSession->addCartId($order->id(), CartSessionInterface::COMPLETED);
    

    Why is this marked completed?

  3. +++ b/modules/cart/src/Form/AddToCartForm.php
    @@ -201,13 +213,38 @@ class AddToCartForm extends ContentEntityForm implements AddToCartFormInterface
    +      $form_state->setRedirect('commerce_checkout.form', ['commerce_order' => $order->id()]);
    

    This adds a hard dependency to the checkout module. We really need the checkout module to just provide a "direct to checkout" formatter and form. The issue is how do we extend Cart or prevent duplicated code.

sorabh.v6’s picture

Assigned: sorabh.v6 » Unassigned
Berdir’s picture

Status: Needs work » Needs review

Thanks for the review @mglaman.

In my use case, I did *not* want users to have a cart, but it's currently not possible to have a checkout without the card module. Or at least it wasn't in march when I worked on this. That's why I used cart FALSE and added it as completed, that's the old trick to allow anonymous users checkout access. See #19, which also explains the dependency thing.

Maybe the cart behavior should be a setting? But in most cases I think you don't want a cart with a direct-to-checkout feature?

Berdir’s picture

Status: Needs review » Needs work
mglaman’s picture

We're dancing on the issue where checkout and cart are too coupled. I think the solution is a checkout formatter which, unfortunately, has to mimic part of the cart form. Maybe we can move the order item from (AddToCartForm) to order as order item form? Not sure. Moving that into two formatters (Add to Cart, Direct to Checkout) helps solve part of the problem. Checkout access can then only care if it is a draft order. Maybe allow cart to interject.

ptmkenny’s picture

FileSize
16.1 KB

Re-rolled #27 for Commerce 2.2.

Bad patch, ignore.

ptmkenny’s picture

Re-rolled #27 again for Commerce 2.2 (previous patch had an unncessary file).

Concerns in #31, #33, and #35 have not been addressed; this re-roll is simply to supply a patch that can be used with the latest version of Commerce to keep sites already using the (needs work) patch up-to-date.

ptmkenny’s picture

mygumbo’s picture

Do you have the patch for Commerce 2.3? Thanks for working on this.

xSDx’s picture

Adding patch for 2.4

streger’s picture

Status: Needs work » Needs review

Thanks @xSDx
It works as expected on Drupal 8.4.5 and Commerce 2.4 when I enabled 'Skip cart, create a new order and immediately start the checkout process.' on field views and field display formatter.

The last submitted patch, 37: commerce-direct-checkout-2.2-2810723-37.patch, failed testing. View results

shaal’s picture

Status: Needs review » Reviewed & tested by the community

Patch #40 works great (Drupal 8.4.5, Commerce 2.4), Thank you!

I used it for a license+subscription product. A "Checkout" button appears instead of "Add to Cart".
Clicking on "Checkout" button loads the checkout page.

It took me some time to find the specific comment that explains how to make 'skipping cart' work (after applying this patch).
To save you some time, here's how you enable the skipping cart feature -

  1. Commerce => Configuration => Products => Product Type => Manage Display
  2. Variations should have the format "Add to cart form"
  3. Click on the Configuration Gear on the right side of 'Variations' line
  4. Enable 'skip cart'
  5. Click on the Update button
  6. Click on the Save button at the bottom of the page
shaal’s picture

Status: Reviewed & tested by the community » Needs work

The patch #40 was working on Drupal Commerce 2.4,
but now it's is failing with Drupal Commerce 2.5
:(

Maxime Gilbert’s picture

shaal’s picture

Status: Needs work » Reviewed & tested by the community

@Maxime Gilbert, Thank you for the patch #45! It worked as expected on Drupal 8.5, with Drupal Commerce 2.5

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 45: commerce-direct-checkout-45.patch, failed testing. View results

Maxime Gilbert’s picture

Corrected redirection pattern on AddToCartFormTest::testSkipCart():

preg_match('|checkout/(\d+)/order_information$|', $this->getUrl(), $matches);
$this->assertNotEmpty($matches, 'Correctly redirected to checkout');
Maxime Gilbert’s picture

Updated patch: I have forget one another pattern test.

Maxime Gilbert’s picture

Again, wrong patch: the redirection URL is not the same for authenticated user and anonymous user: checkout/{order_id}/order_information VS checkout/{order_id}/login.

joachim’s picture

Commerce => Configuration => Products => Product Type => Manage Display
Variations should have the format "Add to cart form"
Click on the Configuration Gear on the right side of 'Variations' line
Enable 'skip cart'

This seems like an odd place to put this setting.

I would have expected it to be a property of the order type. Or the product variation type, if more granularity is required.

We have these bundle entities which can easily hold configuration, so it seems weird to bury functionality in the widget settings.

Maxime Gilbert’s picture

This seems like an odd place to put this setting.

I totally agree with @joachim even if in some cases it make sense to handle the form displayed from the formatter settings. It allows us to choose what to display according a particular context.

But we don't really have the choice and the need to require the Cart module is very weird when we don't use any of its features in any way.

The Cart module should not be a dependency of the Checkout one. But this will require to refactor some part of the Commerce module more than this patch do it. We should have the choice of both an "Add to cart" form from the Cart module and a "Direct checkout" form from the Checkout module. Maybe for an another version.

I needed the "Direct checkout" feature very quickly so I ported the patch from 2.4 to 2.5 (all thanks go to @Berdir, @ptmkenny and @xSDx).

mlecha’s picture

Wondering if the patch in #50 can be applied cleanly to the new release of Drupal Commerce 2.8 on Drupal 8.5.6?

A longterm solution for skipping the cart would be ideal.

iamdroid’s picture

@mlecha, #50 works for me on 2.8/D8.5.6

usarthur’s picture

#50 also worked on 2.7/D8.5.3

shaal’s picture

#50 patch failed for Drupal 8.6.1 + Commerce 2.10

zenimagine’s picture

The "Add to cart" button should be replaced by "Buy" and deactivate the quantity

willeaton’s picture

Patch needs rerolling for commerce 2.10. The patch no longer applies however worked fine previously

mlecha’s picture

@zenimagine Is your suggestion is possible with Drupal 8.6.1 + Commerce 2.1.0, or you're just making a suggestion of future development for Drupal Commerce?

Should it be possible to adjust patch #50 for Drupal 8.6.1 + Commerce 2.1.0?

There doesn't seem to be another solution for direct checkout functionality.

idiaz.roncero’s picture

Yep, it's not working anymore.

I also think this functionality should be on Commerce's core or a contrib module. It is a really common case. In my example, i'm selling different kinds of subscriptions and the typical user will only buy one, so the cart page is an completely unnecesary step.

joachim’s picture

+++ b/modules/cart/src/Form/AddToCartForm.php
@@ -202,12 +214,35 @@ class AddToCartForm extends ContentEntityForm implements AddToCartFormInterface
     $cart = $this->cartProvider->getCart($order_type_id, $store);

This line should be in the condition block for using a cart, as it's pointless if we're not using a cart.

Berdir’s picture

No it is not pointless. It is required to give anonymous users permission to be able to go through the checkout of that order.

It's not a nice solution, it's basically something I also did in D7 projects, by putting direct-checkout orders into the cart order list as completed.

willeaton’s picture

Ive re-rolled the patch so at least it doesn't fail now

shaal’s picture

Confirming #63 patch is working on Drupal Commerce 2.10 with Drupal 8.6.2
Thank you @willeaton

joachim’s picture

+++ b/modules/cart/src/Form/AddToCartForm.php
@@ -202,12 +214,35 @@ class AddToCartForm extends ContentEntityForm implements AddToCartFormInterface
     $cart = $this->cartProvider->getCart($order_type_id, $store);
-    if (!$cart) {
-      $cart = $this->cartProvider->createCart($order_type_id, $store);
+    if ($form_state->get(['settings', 'skip_cart'])) {
+      // Create the new order.

> No it is not pointless. It is required to give anonymous users permission to be able to go through the checkout of that order.

So are you saying that calling getCart() has side-effects which are necessary in the if() block for skip_cart? If so, the call to getCart() needs a comment to explain that, otherwise a future developer might think the same thing I did, which is that it can be moved to the else{} block as that's the only place $cart is used.

remaye’s picture

The patch in #63 doesn't work with DC 8.x-2.9 as in /modules/cart/src/Form/AddToCartForm.php :

public function __construct(EntityRepositoryInterface $entity_repository, ...
     parent::__construct($entity_repository, $entity_type_bundle_info, $time);

has been changed to :

public function __construct(EntityManagerInterface $entity_manager, ...
    parent::__construct($entity_manager, $entity_type_bundle_info, $time);

The patch works again if modified as following :

lines 40 and 41 :
EntityRepositoryInterface $entity_repository
>>> EntityManagerInterface $entity_manager

line 42 :
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
>>> parent::__construct($entity_manager, $entity_type_bundle_info, $time);

But is it safe doing it that way... ?

.../... I tried it and it seems to work well...

flocondetoile’s picture

@remaye The safe and right way is to update DC on latest version 2.11.

ElusiveMind’s picture

Updated to work with v2.11

ElusiveMind’s picture

Jeff Veit’s picture

#69 works for me on 2.11.

Thank you.

kclarkson’s picture

#69 works great for me on 2.11.

Much appreciated. It makes it so much smoother for end users. Thanks again!

johnvenpin’s picture

Got working also with commerce-direct-checkout-69.patch and 8.6.4-2.11 Commerce 2.11

To spare a bit of clicking around the following worked

../admin/commerce/config/product-types

then select your product type
then Manage display
then cog on Variations field
then check Skip cart, create a new order and immediately start the checkout process.

MrPeanut’s picture

I'm on 2.11 but I get the following error when applying the patch from #69:

error: while searching for:
  protected function actions(array $form, FormStateInterface $form_state) {
    $actions['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add to cart'),
      '#submit' => ['::submitForm'],
    ];


error: patch failed: modules/cart/src/Form/AddToCartForm.php:181
error: modules/cart/src/Form/AddToCartForm.php: patch does not apply
Checking patch modules/cart/tests/src/Functional/AddToCartFormTest.php...
Hunk #1 succeeded at 307 (offset 7 lines).
Checking patch modules/cart/tests/src/Functional/CartBrowserTestBase.php...
Checking patch modules/product/config/schema/commerce_product.schema.yml...
Hunk #1 succeeded at 110 (offset 27 lines).
Checking patch modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php...
Checking patch modules/product/src/ProductLazyBuilders.php...
drupgirl’s picture

Just an FYI: I had this working with the patch awhile back but had to abandon this route due to folks being able to use the back button or just click out of the workflow. If you're using licenses the license gets applied before they checkout. So if the user isn't truly committed to checking out and starts hoping out of the workflow -- using the back button, using another link -- then they cannot find their way back to checkout/#, and there's no cart to provide them a new path to get there. In this case you may want to consider going on the order type fullfillment path. Idk, I didn't try that before I abandoned this option.

Also, as far as applying patches -- try moving the ones you want to apply cleanly to the top of you patch stack. I know currently between commerce/license/recurring the patch list is long. Reordering has saved me many times.

Mohsen Molaie’s picture

#69 works great for me on 2.12.
Thanks.

mygumbo’s picture

I've applied #69 to 2.12 and it's working. However, the view Checkout Order Summary does not display on the checkout page, eg /checkout/260/order_information, except for user 1.

Londova’s picture

Is there any reason why this issue is NOT closed and implemented in the Commerce Core?

namitasaxena’s picture

I tried patch of comment #50
then "Add to cart" button disappeared, there is no any button on product page after applying patch
Can anyone please help???

miiimooo’s picture

Status: Needs work » Needs review

Patch applies cleanly with 2.13.0 / 8.7.3 and works as expected

Seems even to come with a test. Could this be committed or is the approach the problem?

lawxen’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

@miiimooo patch of #69 can't be applied to commerce:2.13 or newest commerce:2.x-dev

lawxen’s picture

Re-roll #69 for newest commerce:2.x-dev

Status: Needs review » Needs work

The last submitted patch, 81: 2810723-81.patch, failed testing. View results

AjitS’s picture

Issue tags: -Needs reroll

Removing the tag as the patch was rerolled.

muaz91’s picture

Thank you @lawxen, patch #81 is working for me.

How to use:

1. go to your product display settings (/admin/commerce/config/product-types/default/edit/display)
2. in Variations field, click the gear icon located at the of the field
3. The gear when clicked, you will get format settings displayed on the Format column
4. Tick Skip cart, create a new order and immediately start the checkout process
5. Do not forget to click Update on the Format column, and then save the display

To tried out the setting, go to the product page (eg: /product/1) and click checkout. you will automatically redirect to checkout page

muaz91’s picture

Status: Needs work » Reviewed & tested by the community
joelpittet’s picture

I'll give a big +1 RTBC to this latest patch it works great.

joelpittet’s picture

Reroll just some minor fuzz

patching file modules/cart/src/Form/AddToCartForm.php
patching file modules/cart/tests/src/Functional/AddToCartFormTest.php
patching file modules/cart/tests/src/Functional/CartBrowserTestBase.php
patching file modules/product/config/schema/commerce_product.schema.yml
patching file modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php
Hunk #2 succeeded at 41 with fuzz 1.
patching file modules/product/src/ProductLazyBuilders.php
joelpittet’s picture

There is a @TODO in there, I'm comfortable with it but maybe the maintainers have a better approach in mind?

+++ b/modules/cart/src/Form/AddToCartForm.php
@@ -205,12 +217,36 @@ class AddToCartForm extends ContentEntityForm implements AddToCartFormInterface
+      // Add the order as a completed cart to allow anonymous checkout access.
+      // @todo Find a better way for this.
+      $this->cartSession->addCartId($order->id(), CartSessionInterface::COMPLETED);
+      $form_state->setRedirect('commerce_checkout.form', ['commerce_order' => $order->id()]);

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 87: 2810723-87-reroll-69-direct-checkout.patch, failed testing. View results

Anas_maw’s picture

Status: Needs work » Reviewed & tested by the community

+1 for RTBC

renguer0’s picture

Tried #69, #81 and 87 and their didn't apply. I'm in last dev of Commerce.

Thanks for all you work.

baikho’s picture

Reroll against HEAD of dev

baikho’s picture

Status: Reviewed & tested by the community » Needs review

Status: Needs review » Needs work

The last submitted patch, 92: commerce-direct_checkout-2810723-92.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

renguer0’s picture

Well, I saw this module: https://www.drupal.org/project/commerce_cart_redirection and it's working good.

I didn't test it deeply, maybe you want to check by your own.

hodba’s picture

The patch is not applying against 2.19. Can anyone help with it?

rob_eyre’s picture

Need to modify the patch file around line 67 (sorry, I'm a hopeless newbie, don't know how to upload this revised patch)

@@ -205,14 +217,39 @@ class AddToCartForm extends ContentEntityForm implements AddToCartFormInterface                                                                                                $purchased_entity = $order_item->getPurchasedEntity();

     $cart = $order_item->getOrder();
-    if (!$cart) {
+    if ($form_state->get(['settings', 'skip_cart'])) {
       $order_type_id = $this->orderTypeResolver->resolve($order_item);
       $store = $this->selectStore($purchased_entity);
-      $cart = $this->cartProvider->createCart($order_type_id, $store);
+      // Create the new order.
+      /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
+      $order = $this->entityTypeManager->getStorage('commerce_order')->create([
+        'type' => $order_type_id,
+        'store_id' => $store->id(),
+        'uid' => $this->currentUser()->id(),
+        'cart' => FALSE,
+      ]);
+
+      $order->addItem($order_item);
+      $order->save();
+
+      // Other submit handlers might need the cart ID.
+      $form_state->set('cart_id', $order->id());
+
+      // Add the order as a completed cart to allow anonymous checkout access.
+      // @todo Find a better way for this.
+      $this->cartSession->addCartId($order->id(), CartSessionInterface::COMPLETED);
+      $form_state->setRedirect('commerce_checkout.form', ['commerce_order' => $order->id()]);
+    }
+    else {
+      if (!$cart) {
+        $order_type_id = $this->orderTypeResolver->resolve($order_item);
+        $store = $this->selectStore($purchased_entity);
+        $cart = $this->cartProvider->createCart($order_type_id, $store);
+      }
+      $this->entity = $this->cartManager->addOrderItem($cart, $order_item, $form_state->get(['settings', 'combine']));
+      // Other submit handlers might need the cart ID.
+      $form_state->set('cart_id', $cart->id());                                                                                                                                                     }
-    $this->entity = $this->cartManager->addOrderItem($cart, $order_item, $form_state->get(['settings', 'combine']));
-    // Other submit handlers might need the cart ID.
-    $form_state->set('cart_id', $cart->id());
   }                                                                                                                                                                                            
   /**
floydm’s picture

Attached is an attempt to reroll the patch from 92 against commerce 2.19. I did a three way merge and then accepted the changes from the previous patch where I could.

Apologies that I am unfamiliar with the history of this patch and how best to test it. I'm bringing a site I've inherited (but am unfamiliar with) up-to-date. Previously it was running Commerce 2.16 patch from 69.

I hope this works for folks.

mlecha’s picture

Patch #98 applied cleanly for me on Commerce 2.19 with Drupal 8.9. Tested direct checkout/skip cart in test mode with Stripe with no issues here on a local dev site.

Thanks for the patch update floydm. Much appreciated.

fishfree’s picture

Status: Needs work » Reviewed & tested by the community

I also applied Patch #98 against Commerce 2.19 with Drupal 8.9. Everything works perfectly. Many thanks!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 98: commerce-direct_checkout-2810723-98.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

piggito’s picture

Status: Needs review » Needs work

The last submitted patch, 102: commerce-direct_checkout-2810723-102.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

valic’s picture

I think we should have more options for skipping carts, then just on add to cart form

* Per order type - case where you create automatic orders, send to the customer and he lands directly on checkout, without ability to use cart
(like some specific fees, I had case for warranty fees)
- this would provide more general ability to skip cart

* Per product type - case where you have specific product which does not need cart, but also there is no need for separate order type
- this would provide more granular ability to skip cart

ptmkenny’s picture

Issue summary: View changes
joelpittet’s picture

@valic re #104 Those might be better suited for a separate/follow-up feature request or do they tie in with the current patch?

We've been using the patch in here for quite some time and wonder what is needed to finish it and get it committed? My guess is the test failures need to be resolved (if they are related), but if so would this feature be considered?

Status: Needs review » Needs work

The last submitted patch, 107: 2810723-107-direct-checkout.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

ptmkenny’s picture

Edit: Comment removed because I found the cause, and it wasn't this patch.

Berdir’s picture

re #104, this is configurable in the formatter, so it already *is* per order type and product type?

re #109: Yeah, there are also tons of test fails that kind of indicate that there's something broken on the page. That said, the serialization error is not your problem, that just happens while handling the actual error, the first one is the problem you need to look at.

joelpittet’s picture

Thanks @berdir, the manual testing without the cart shows that the errors are probably due to the API for the extra param $skip_cart for public function addToCartForm($product_id, $view_mode, $combine, $skip_cart, $langcode) {

I'll see if I can remove it easily

joelpittet’s picture

I'm not sure where I can get the $skip_cart inside the \Drupal\commerce_product\ProductLazyBuilders::addToCartForm without passing it in, I'd guess it's possible but anybody know off hand?

Berdir’s picture

+++ b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php
@@ -92,6 +102,7 @@ class AddToCartFormatter extends FormatterBase {
           $product->id(),
           $view_mode,
           $this->getSetting('combine'),
+          $this->getSetting('skip_cart'),
           $langcode,
         ],

a bit hard to see from context, but this is the list of arguments passed to the lazy builder, so that seems to be here?

Berdir’s picture

+++ b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php
@@ -104,7 +115,9 @@ class AddToCartFormatter extends FormatterBase {
   public static function isApplicable(FieldDefinitionInterface $field_definition) {
-    $has_cart = \Drupal::moduleHandler()->moduleExists('commerce_cart');
+    // This formatter requires both commerce_checkout and commerce_cart enabled,
+    // commerce_checkout depends on cart.
+    $has_cart = \Drupal::moduleHandler()->moduleExists('commerce_checkout');
     $entity_type = $field_definition->getTargetEntityTypeId();
     $field_name = $field_definition->getName();

this seems to be the problem, I don't remember exactly why I made this change, but for some reason, there are tests that enable commerce_cart but not checkout to test product add to cart form, and the result of this is that the form doesn't show up. Not quite sure what the best way forward is. This setting _does_ depend on commerce_checkout. So maybe needs a different implementation, not sure.

That doesn't explain why it doesn't work on your actual site I would assume, but maybe there's a conflict with another patch or customization?

Berdir’s picture

> So maybe needs a different implementation, not sure.

Yeah, I suspect that a way forward would be a subclass of \Drupal\commerce_cart\Form\AddToCartForm in commerce_checkout and instead of passing the argument in, \Drupal\commerce_product\ProductLazyBuilders::addToCartForm() would be one of the two forms, plus conditional visiblity of the checkbox in \Drupal\commerce_product\Plugin\Field\FieldFormatter\AddToCartFormatter.

valic’s picture

Updated patch, with going back on settings per order type. Now cart / checkout are not tied (in regards of future removal of dependency among them).

If commerce_checkout is not enabled, cart module would work as is, and for that reason I moved tests from cart to checkout module.
We don't need to test cart, but checkout. Without checkout module cart can't have skip cart option.
One test still should failed (checkout text button problem)

  1. There is a setting on Order type
  2. AddToCart from is unchanged - we allow normal processing of orders, and in CartProvider we are marking cart as not active
  3. While those order types does not have cart, AddToCart is going to always create new order
  4. If commerce_checkout is not enabled, there is no option for removing skip the cart option
  5. Added event subscriber for set redirection - as in commerce_direct_checkout
  6. Most of the logic is tied if order have cart 0 or 1, so it should not be causing issues cart module

TODO
- altering Add to cart -> in Checkout. We can't do this now easily. We could, but we would skip order item resolving.
Form alter is not going to work. We could do the resolve on lazy builder, and push as before skip_cart settings (this seems now easiest)

With regards of event subscriber and checkout button, maybe we should do swapping class for AddToCart, even with pushing through lazy builder would be simpler for now

valic’s picture

Status: Needs work » Needs review

Let's confirm test failure (one hopefully)

Status: Needs review » Needs work

The last submitted patch, 116: 2810723-116.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

valic’s picture

My mistake, running locally Drupal 9.x. Small change to the patch.

valic’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 119: 2810723-118.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

valic’s picture

Status: Needs work » Needs review
FileSize
13.97 KB
872 bytes

Rerolling patch from #119 with final change for ability to change "Add to cart" button text.

We can easily overwrite that button within checkout module.
Order item is inside form object available (forgot on that, it was late yesterday), therefor we can do resolving. And check if resolved order type have skip cart enabled.

Tests should be green now.

TODO
- naming: do we use skip_cart key, or maybe direct_checkout naming, while everything is inside checkout module

Impact on cart should be non existing, even still not sure if we should do inside createCart this

// Check if order type is configured to skip cart.
    $order_type = $this->orderTypeStorage->load($order_type_id);
    $skip_cart = $order_type->getThirdPartySetting('commerce_checkout', 'skip_cart');

But don't see other way, without changing AddToCart form, which we haven't now touched. And keep almost all changes in commerce_checkout

valic’s picture

Renamed key from skip_cart to checkout_direct, but in UI we show to users "Direct checkout"
(checkout_direct as key seems more logical, as there is checkout_flow, etc.. even direct_checkout is probably proper - native speakers can decide that better).

Adjusted tests a little, and added additional check that order is not visible on cart.

What is left is to decide if someone changes setting on order type to disable direct checkout, and then later enable, existing cart's are going to be carts then still. But I would rather left that now as is. It's up to each person maybe to handle these specifics, not sure we need to force it here? (I see slim chanches that setting on order type is going to be updated regularly, causing incosistency in behavior).

When the checkout module is not going to depend anymore on cart, we can add wrapper or force default value for direct checkout with moduleExists.

valic’s picture

Status: Needs review » Needs work

We can completly decoupled the logic from cart provider, patch coming in a half hour

valic’s picture

Status: Needs work » Needs review
FileSize
11.58 KB
13.39 KB

Reroll of #123 with removing all changes from commerce_cart.
Now all logic resides in commerce_checkout.

Added service provider to swap CartEventSubscriber with CheckoutCartEventSubscriber when commerce_cart is enabled.
That event subscribers handles all logic around direct checkout, and if is not enabled it pass back to original CartEventSubscriber
(so we removed as well that message when direct checkout is enabled).

Service provider in a way does not make sense now while checkout depends on cart, but when this lands https://www.drupal.org/project/commerce/issues/2948332, then it will not break anything (because of DI related to cart module).
(but then we would need to split that event, so that without cart module enabled we can make an redirect to checkout directly)

valic’s picture

Cleaning unused namespaces

ptmkenny’s picture

Issue summary: View changes

Updating IS to include documentation on how to use the latest patch.

ptmkenny’s picture

(Edit) Tested #126 manually on my commerce store; direct checkout functionality works as expected, but I can't use the module with webprofiler (see next post).

ptmkenny’s picture

When I enabled the webprofiler submodule of the Devel module, Commerce Checkout breaks with the following error:

The website encountered an unexpected error. Please try again later.
TypeError: Argument 4 passed to Drupal\commerce_checkout\EventSubscriber\CheckoutCartEventSubscriber::__construct() must be an instance of Drupal\Core\Entity\EntityTypeManager, instance of Drupal\webprofiler\Entity\EntityManagerWrapper given, called in /app/web/core/lib/Drupal/Component/DependencyInjection/Container.php on line 259 in Drupal\commerce_checkout\EventSubscriber\CheckoutCartEventSubscriber->__construct() (line 65 of modules/contrib/commerce/modules/checkout/src/EventSubscriber/CheckoutCartEventSubscriber.php).
Drupal\commerce_checkout\EventSubscriber\CheckoutCartEventSubscriber->__construct(Object, Object, Object, Object, Object, Object) (Line: 259)
Drupal\Component\DependencyInjection\Container->createService(Array, 'commerce_cart.cart_subscriber') (Line: 173)
Drupal\Component\DependencyInjection\Container->get('commerce_cart.cart_subscriber') (Line: 71)
Drupal\webprofiler\EventDispatcher\TraceableEventDispatcher->dispatch('kernel.response', Object) (Line: 191)
Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object, Object, 1) (Line: 173)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 38)
Drupal\webprofiler\StackMiddleware\WebprofilerMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Steps to reproduce

1. Enable Commerce modules, including Checkout.
2. Enable Webprofiler module.
3. Go to any page of the site.

valic’s picture

Sorry, fixed. It should be working now with devel

valic’s picture

FileSize
1.4 KB

And correct interdiff attached

deminy’s picture

I tried patch #130 tonight; unfortunately it seemed not working when using a PayPal method as the only payment gateway. In this case, an order is created without making a payment through PayPal.

ptmkenny’s picture

@deminy Could you explain how you configured Commerce? It would be great if you could provide step-by-step instructions, preferably from a fresh Drupal install, so that the error can be reproduced and fixed.

deminy’s picture

It will take some time to look into the issue with my current settings and using a fresh installation. I will try to provide more details this week. Thanks

deminy’s picture

I did some more tests before the holiday, and here is what I found.

First, the patch is exactly what I was looking for for my use case (I'd say it's the best solution comparing to some other attempts I found previously).

The problem is related to the Commerce PayPal module I installed. There are two options to create a new checkout flow:

  1. Multistep - Default
  2. PayPal Checkout

The first one works fine, but the second one (PayPal Checkout) doesn't work. If I use the "PayPal Checkout" checkout flow and try to checkout, I can click the "review", "checkout" buttons to complete checkout directly (without seeing a PayPal popup).

I'm not sure what caused the issue since it happened with PayPal only; it might not be an issue from the patch. I also tried to reproduce the problem with a fresh installation; however, there were too many modules/steps involved, so I gave up doing that.

As said, the patch doesn't work with the "Multistep - Default" workflow. Thanks

interlated’s picture

This patch applies against dev. The add to cart button generated by a view does not work, and I can't see an alternative 'direct checkout' button.

cferthorney’s picture

The patch at #130 is working with 2.28. Requires one more for RTBC

*edited to reflect update to 2.28 working as expected*

Rob230’s picture

Status: Needs review » Reviewed & tested by the community

Path #130 working well for me on D9. Required reconfiguring because we previously had an older patch where it was configured on the product type display.

ptmkenny’s picture

Status: Reviewed & tested by the community » Needs work

Unfortunately after the 2.30 release, this patch no longer applies. Needs a reroll.

scotthooker’s picture

scotthooker’s picture

geek-merlin’s picture

Status: Needs work » Needs review

Run, testbot!

scotthooker’s picture

Go for it I just needed the patch pretty sharpish ;)

GlarDup’s picture

Patch 141 does exactly what I needed. Thanks!!!

RgnYLDZ’s picture

I can also confirm that patch 141 works perfectly with commerce 2.31

ibis’s picture

Status: Needs review » Needs work

Unfortunately after the 2.32 release, this patch no longer work. Needs work.

znerol’s picture

Status: Needs work » Needs review

Patch in #141 still applies fine to 2.32, no need to reroll.

Status: Needs review » Needs work

The last submitted patch, 141: 0001-Reroll.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

znerol’s picture

Oh, so applies fine but now produces test errors. Needs work then.

jsacksick’s picture

@znerol: The test errors are unrelated. putting this back to needs review.

znerol’s picture

Opened #3317738: Add an option to disable the add to cart message on a certain order type in order to avoid having to replace the commerce_cart.cart_subscriber.

balis_m’s picture

Status: Needs work » Needs review
FileSize
11.65 KB

Using Drupal 10 and commerce 8.x-2.x-dev with patch #141 throws the following error:

TypeError: Drupal\commerce_checkout\EventSubscriber\CheckoutCartEventSubscriber::checkRedirectIssued(): Argument #1 ($event) must be of type Symfony\Component\HttpKernel\Event\FilterResponseEvent, Symfony\Component\HttpKernel\Event\ResponseEvent given in Drupal\commerce_checkout\EventSubscriber\CheckoutCartEventSubscriber->checkRedirectIssued() (line 131 of modules/contrib/commerce/modules/checkout/src/EventSubscriber/CheckoutCartEventSubscriber.php).

This patch solves the TypeError issue and small coding standards issues.

znerol’s picture

#3317738: Add an option to disable the add to cart message on a certain order type is in, so CheckoutCartEventSubscriber can now be implemented without overriding CartEventSubscriber.

Yasser Samman’s picture

I had to re-roll #152 to latest dev and test on 2.36.

Yasser Samman’s picture

FileSize
11.61 KB

Test failed because of wrong arguments in CheckoutCartEventSubscriber.
Here's another try.

coffeemakr’s picture

Instead of altering the session and the order manually, the CartProvider::finalizeCart can be used.

I think this would make it more future proof and simplify the code.

coffeemakr’s picture

I have noticed that finalizeCart is only called in the event commerce_order.place.pre_transition (and therefore the order->cart is set to false). So the cart flag is true until the end of the checkout process.

With the current patch, functions that depend on the flag being set at the end break. For example the commerce_cart_expiration. Uncompleted order will therefore never expire.

znerol’s picture

Instead of altering the session and the order manually, the CartProvider::finalizeCart can be used.

I think this would make it more future proof and simplify the code.

Nice idea! CartProvider::finalizeCart also clears a static cache in CartProvider.

joelpittet’s picture

@coffeemakr I'm not sure how the test passed but there is an error introduced by the patch in #154
$order = Order::load(2);+ $this->assertEquals(0, $order->get('cart')->value);
And a nit pick for the space on the docblock in the test dropped a space before the /**.

Thank you for the clean-up btw!

coffeemakr’s picture

@joelpittet: Of course thats correct. Here's a fixed version.

joelpittet’s picture

Status: Needs review » Reviewed & tested by the community

Thank you @coffeemakr, I'll set this back to RTBC

Anas_maw’s picture

+1 for RTBC

RyanCMcConnell’s picture

Any idea when this will be merged? We're using this code and it works flawlessly.

jsacksick’s picture

Status: Reviewed & tested by the community » Needs work

I don't understand why this patch became so complicated... Can't we simply handle this via a form state redirect? I don't like the fact that we swap the cart subscriber like this... Which could be decorated/removed on custom installations...
Also, what about Headless sites? Will that cause a redirect too? This should only apply to the form, not every add to cart, even ATC made outside of the form context?

jsacksick’s picture

I would expect code similar to this https://www.drupal.org/project/commerce/issues/2907461#comment-15316055 to handle the redirection... (i.e. an extra submit handler that does the redirect, added by the commerce_checkout module).

jsacksick’s picture

I'm wondering if we can't support both redirecting to cart/checkout at the same time? Perhaps the cart module could define a "redirect_to_cart" setting as well?
Or we allow specifying a path to redirect... The only problem might be the required route parameters...

rgpublic’s picture

Wasn't the complicated patch also due to the need to suppress the unwanted cart message? We now have this #3317738 so perhaps this could indeed be revisited?

jsacksick’s picture

Oh you're right, that could be the reason, so I believe the patch can be greatly simplified.

valic’s picture

@jscksick Yes, the most relevant comment would be #125 https://www.drupal.org/project/commerce/issues/2810723#comment-13832755
where are the changes occurred

All changes have been moved to the commerce_checkout module, and back then we still had "add to cart message" which is not configurable

now it's not needed anymore to swap that, and should be separate subscriber perhaps

tBKoT’s picture

Status: Needs work » Needs review
FileSize
6.96 KB
10.32 KB

This is the patch without altering the event subscriber. It adds changes to the "Add to cart" form in form_alter. The custom submit handler adds a redirect to the checkout step

jsacksick’s picture

  1. +++ b/modules/checkout/config/schema/commerce_checkout.schema.yml	(date 1701375521101)
    @@ -5,6 +5,9 @@
    +    checkout_direct:
    

    I wonder if we should rename this to "checkout_redirect", but I'll defer to @rszrama for this.

  2. +++ b/modules/checkout/commerce_checkout.module	(date 1701375828203)
    @@ -181,6 +191,24 @@
    +    $order_type_resolver = \Drupal::service('commerce_order.chain_order_type_resolver');
    +    $order_type_id = $order_type_resolver->resolve($order_item);
    +    /** @var \Drupal\commerce_order\Entity\OrderTypeInterface|null $order_type */
    +    $order_type = \Drupal::entityTypeManager()->getStorage('commerce_order_type')->load($order_type_id);
    

    Can't we get the order from the order item here??

  3. +++ b/modules/checkout/commerce_checkout.module	(date 1701375828203)
    @@ -181,6 +191,24 @@
    +      $form['actions']['submit']['#submit'][] = 'commerce_checkout_direct_checkout_form_submit';
    

    maybe rename this to commerce_checkout_add_to_cart_form_submit()?

@tBKoT: Thank you for this patch, I'm still wondering if we could include within the same patch the ability to redirect to the cart page as well.. Or perhaps we could simply expose an url to redirect to after adding to cart though it may be problematic due to the route parameters etc...

jsacksick’s picture

Ok what about the following proposal:

We add a new checkbox under the "Cart settings" fieldset that says:
[x] Redirect the customer after an item is added to the cart.

When the checkbox is checked, we expose a "Destination" setting select list where we have 2 options:
* Cart
* Checkout.

The setting is added from the cart module and the redirect is done from AddToCartForm::submitForm() directly.

Note that we don't have to store 2 new settings, but we can default the checkbox to TRUE only if we have a value for the destination.
We can call the setting "cart_redirect" (See screenshots below):

Update: On the screenshot, the select list says "Redirection destination", let's just skip "Destination".

jsacksick’s picture

After discussing this with @rszrama on Slack, we think this setting should be moved next to other similar settings (such as the "combine" setting), which means putting this setting back as a formatter setting....

tBKoT’s picture

Here is the patch that provides redirect to cart|checkout in the "Add to cart" field formatter settings.

jsacksick’s picture

Do we really need to recreate an order? I'm confused?
Sure we need all of this??

      /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
+      $order = $this->entityTypeManager->getStorage('commerce_order')
+        ->create([
+          'type' => $order_type_id,
+          'store_id' => $store->id(),
+          'uid' => $this->currentUser()->id(),
+          'cart' => FALSE,
+        ]);
+      $order->addItem($order_item);
+      $order->save();
+
+      // Add the order as a completed cart to allow anonymous checkout access.
+      // @todo Find a better way for this.
+      if ($this->currentUser()->isAnonymous()) {
+        $this->cartSession->addCartId($order->id(), CartSessionInterface::COMPLETED);
+      }

Btw, the idea was to go with a single setting. We add a "redirect_destination" setting, and the "redirect" checkbox is checked if it's not empty.
Also, let's use #states so we don't display the select if no redirect destination is set?

tBKoT’s picture

This patch adds only one setting to the field formatter - "redirect_destination".
The "Destination" field uses #states and will be shown when the "redirect" checkbox is checked.
The default value for the "redirect" checkbox depends on the "redirect_destination" value.
Also, there is a custom validation method to clear "redirect_destination" when the "redirect" checkbox is unchecked.

tBKoT’s picture

Add fixes to coding style and tests

tBKoT’s picture

tBKoT’s picture

FileSize
15.45 KB
2.4 KB

@jsacksick
We need to create a new order instead of a cart, as the main idea in this issue is to avoid cart creation and go to the checkout step directly
There is a new patch with a check if the user already has the "draft" order for the selected item to avoid duplicates and use existing order for checkout.