Trying to use the checkout module when commerce_product_reference is not installed results in the following fatal error:

Fatal error: Call to undefined function commerce_product_line_item_types() in .../sites/all/modules/contrib/commerce/modules/checkout/includes/commerce_checkout.pages.inc on line 45

And when installing it then I'm forcefully redirect to &lt>front&gt> because I do not have any product line items :)

Not sure what's the fix:

a) Checkout only supports product line items (why?) then it's missing a dependency on that module
b) It shouldn't limit to product line items only.. ;)

Comments

berdir’s picture

FYI:

For my use case, " if (commerce_line_items_quantity($wrapper->commerce_line_items, array_keys(commerce_line_item_types())) == 0) { " seems to work just fine, but I'm just using the default checkout process when coming back from the offsite payment and for the confirmation.

a) would be kinda unfortunate for me, as the only way to work around that would be to hook_menu_alter() the checkout callback and do my own checks.

rfay’s picture

Status: Active » Needs review
StatusFileSize
new448 bytes

SHouldn't it just get a dependency?

bojanz’s picture

The offending function is quite small:

/**
 * Returns an array of product line item types.
 */
function commerce_product_line_item_types() {
  $types = array();

  foreach (commerce_line_item_types() as $type => $line_item_type) {
    if (!empty($line_item_type['product'])) {
      $types[] = $type;
    }
  }

  return $types;
}

If we just move it commerce_line_item, then checkout continues to work (it already depends on order which depends on line item).
Seems like that is the only place where we make the product assumption.

Could probably use feedback from Ryan.

berdir’s picture

If it's the only place where a product assumption is made, then why is that check necessary in the first place? (The "check if there are *product* line items" as opposed to a more generic "check if there are line items").

Looking at the git history a bit, the current code was added in #1033050: Support customizable products via the Add to Cart form but that's just a refactoring of the previous check, another refactoring happened in #1047078: Prefix Commerce module governed fields with commerce_ (field rename) and the check was initially added in #842114: Rework the checkout form from multistep to multi-form on the Thu Aug 12 01:20:17 2010 aka quite a long time ago :)

berdir’s picture

StatusFileSize
new709 bytes

Here is a patch for removing the explicit dependency. It's actually even easier than in my example code in #1 because if we allow any type, then we don't need to specify the $types at all.

Maybe still needs feedback from ryan why the check is/was like that...

rszrama’s picture

Title: Undeclared dependency on commerce_product_reference » API change: Allow other modules to verify that an order may proceed to checkout
Category: bug » feature
Status: Needs review » Active

The basic idea is that we have to have some sort of assumption about what should be "checkoutable" and what shouldn't. Allowing any line item to register an order as "checkoutable" isn't sufficient, as who knows what types of dangling line items may collect in orders from modules like Coupon and Shipping. Thus the Cart / Checkout system introduce a dependency on product line item types. Granted, now you can simply declare that your line item type should be considered a 'product' for the purposes of checkout on the site, but that's not necessarily the best solution.

Perhaps we simply need "yet another property" for line item types that mark it as sufficient for an order containing one line item of that type to be checkoutable. This may also require changes to the Cart module, as the Cart / Checkout modules together are geared toward the use case of getting products from a node to a completed order.

I'd be hesitant to monkey with this too much on the 1.x branch, but perhaps what we can do is add a point of extensibility to the bit of logic that checks "is this order checkoutable"? In other words, we could keep the default product requirement for checkout but abstract it out of the router and change it from a falsification to a verification - i.e. instead of one module saying "hey, this order can't be checked out" we'd just be looking for one module to say "hey, this order can in fact be checked out."

And really, I suppose that change actually could go into the 1.x branch.

mr.baileys’s picture

rszrama’s picture

Ahh, thanks Ivo. I knew we'd gone over this before but couldn't remember where. : )

berdir’s picture

Note that the same change would probably need to be added to the line item view when viewing an order. Because that is currently limited to product line item types as well.

GaborTorok’s picture

I share my problem that would be solved by this to show a possibe use case that may give ideas:
I have to provide an option for shop admins to compose orders manually for the customer in response for a quote request for a renewable energy generation system. For this, an order should work even without any products, just by entering titles, unit prices and quantites for line items.

derhasi’s picture

I'm currently workin on a project, where we simply want to make userpoints purchasable, and therefore products are not needed. I try to decouple the current implementation and provide a patch for that.

derhasi’s picture

Status: Active » Needs review
StatusFileSize
new2.51 KB

There is the patch, that simply removes the dependency and builds some wrapper to make it more clear, and so does not change the API in any way.

Status: Needs review » Needs work

The last submitted patch, checkout-without_product_dependency-1458766-12.patch, failed testing.

dippers’s picture

The patch in #12 still uses commerce_product_line_item_types() when I suspect it should be using commerce_checkout_checkoutable_line_item_types().

derhasi’s picture

Status: Needs work » Needs review
StatusFileSize
new729 bytes
new2.52 KB

@Dippers you are totally right. There's the correct patch.

Status: Needs review » Needs work

The last submitted patch, checkout-without_product_dependency-1458766-15.patch, failed testing.

Anonymous’s picture

Issue summary: View changes

fixed tags

berdir’s picture

Not sure how the last patch helps, it adds new functions but the underlying logic stays exactly the same. It should either introduce a hook to check this or introduce a new property that can be set that is named checkoutable, and you can either set product or that to TRUE.

veso_83’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new3.05 KB

This patch adds additional option to select what line_items can be used for the checkout process, you may consider excluding the product line item using this patch and create your own (this will remove the product dependency in the checkout process). This can be done through the admin menu for commerce_checkout module.

dwkitchen’s picture

I have added the menu item that was missing from the last patch so you can get to the settings form, and made the form a system settings form.

I have also namespaces the variable and made the check in the checkout router fall back to the previous behavior if the settings have not been changed.

dwkitchen’s picture

Patch now encoded in UTF-8

rszrama’s picture

Status: Needs review » Active

I'm going to bring this back to my comment #6 above. The approach that developed seems to be rooted in a prior contributor's desire to have a form to make more than one line item "checkoutable", but all it does is provide a user interface without really addressing the underlying issue as declared in the title - allowing other modules to verify an order may proceed to checkout.

As far as I'm concerned, that means it doesn't really make sense to use the patch that's developed, though I do appreciate the effort put into it thus far. What I recommended in #6 was that while a property that determines if a line item is "checkoutable" or not would be an interesting solution, but ultimately I'm hesitant to add that to the data structure at the present time.

My recommendation was to instead create a new function that we use to determine if an order can proceed to checkout based on its contents (e.g. commerce_checkout_order_can_checkout()) that starts with a FALSE return value, can set that to TRUE if it passes the check for product line items, and then allows other modules the opportunity to return a TRUE value as well via a hook. That may involve simply supporting additional line item types, but that wasn't the most interesting part of the solution.

Given this is more abstract and that line item types are currently primarily governed by code, I don't see a need for a user interface for this.

berdir’s picture

A function and a hook sounds fine for me, I'll see if I can find some time and provide a patch, unless someone else beats me to it.

The product check could be a hook implementation (of commerce_product?) too, fewer explicit dependencies are a good thing I think :)

rszrama’s picture

Status: Active » Needs review
StatusFileSize
new5.11 KB

Try this one out. : )

berdir’s picture

Looks nice! Haven't tried it yet, just some documentation nitpicks...

  1. +++ b/modules/checkout/commerce_checkout.api.php
    @@ -42,6 +42,29 @@ function hook_commerce_checkout_router($order, $checkout_page) {
    + *
    + * @param $order
    + *   The order being confirmed for checkout.
    + *
    + * @return
    + *   Boolean value indicating whether or not the order can proceed to checkout.
    

    Not sure if you want to follow the new coding standards, if so, that would be "@param object $order" and "@return true|null" or something like that.

    A common pattern for access hooks (in a way, this is similar to e.g. hook_node_access()) is TRUE to allow unless someone explicitly prevents with FALSE. I don't think that makes much sense here, though, I can't think of any use case why a module would want to forcefully prevent access even if someone else would allow access.

  2. +++ b/modules/checkout/commerce_checkout.module
    @@ -899,6 +899,38 @@ function commerce_checkout_order_uri($order) {
    + *
    + * The default core implementation is in commerce_product_reference.module and
    + * allows any order containing a product line item to proceed to checkout.
    

    Might be useful to reference the function directly instead of the filename? Alternatively as a @see.

berdir’s picture

Status: Needs review » Reviewed & tested by the community

Ok, verified that this works correctly when removing the product => TRUE flag and implementing the hook instead. Feel free to tidy up the function reference (2.) on commit :)

rszrama’s picture

Status: Reviewed & tested by the community » Fixed

Awesome. I added a @see comment but stayed with the inverted logic since the default assumption here is that an order shouldn't be considered "checkoutable" unless some module says so (at least as far as the original logic here was concerned re: line item types on the order).

Thanks for the review!

Commit: http://drupalcode.org/project/commerce.git/commitdiff/f8f056b

Status: Fixed » Closed (fixed)

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

bgilhome’s picture

Sorry to re-open this issue, but just wondering if there is an intention to add a similar call to commerce_cart_checkout_router() used for the 'checkout' menu router item? A patch to achieve this is attached. I also set repeat to FALSE on the dsm() since I was getting duplicate messages, not sure why.

bgilhome’s picture

Status: Closed (fixed) » Needs review
chris matthews’s picture

Status: Needs review » Fixed

@bgilhome, I believe you'll have to open a new issue to address your question in #30

Status: Fixed » Closed (fixed)

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