Problem/Motivation

Every request on a donate page entity does currently create a new order object. This is also true and especially problematic for AJAX requests. Those are for example triggered when changing certain settings on donate page forms that are featuring recurring payments.

Proposed resolution

Store order id in the session and reload it instead of creating a new one upon every request. Also make sure only one line item is kept and updated/re-created upon changes of the amount, donation type etc.

Comments

s_leu created an issue. See original summary.

s_leu’s picture

Status: Active » Needs review
StatusFileSize
new5.14 KB

Here's a first patch

berdir’s picture

Status: Needs review » Needs work
  1. +++ b/salsa_commerce.module
    @@ -189,14 +189,14 @@ function salsa_commerce_donate_order_create_validate($form, &$form_state) {
     function salsa_commerce_create_order($form, &$form_state) {
    -  // Create a new order.
    -  if (!isset($form_state['order'])) {
    +  // Create a new order or get the existing one from the session.
    +  if (!isset($_SESSION['salsa_commerce']['order_id'])) {
         $order = commerce_order_new($GLOBALS['user']->uid);
    

    We need more context here. If you visit another donation page, then this shouldn't persist. Even more so with p2p donations and so on. Get it from form_state or pass a context to the method so that yo ucan define a unique key in the session instead of order_id.

  2. +++ b/salsa_commerce.module
    @@ -252,12 +252,87 @@ function salsa_commerce_create_order($form, &$form_state) {
    +  // Fetch existing line item and delete it in order to add a new one later on.
    +  if (isset($_SESSION['salsa_commerce']['line_item_id'])) {
    +    commerce_line_item_delete($_SESSION['salsa_commerce']['line_item_id']);
    +    unset($order_wrapper->commerce_line_items);
    +  }
    

    why do we need it for the line item exactly? can't we just delete the one that's currently in the order?

  3. +++ b/salsa_commerce.module
    @@ -484,6 +548,9 @@ function salsa_commerce_commerce_checkout_complete($order) {
    +
    +  // Order was completed so user is allowed to begin a new order now.
    +  unset($_SESSION['salsa_commerce']);
    

    this needs to get more flexible too then and needs to look for the order ID in the list of keys and unset just that.

s_leu’s picture

Status: Needs work » Needs review
StatusFileSize
new8.21 KB
new5.74 KB

Alright here the requested changes.

s_leu’s picture

Last patch seemed to cause problem on certain config/version of PHP. Adding improved version

Status: Needs review » Needs work

The last submitted patch, 5: prevent_multiple_orders-2689007-5.patch, failed testing.

berdir’s picture

Just one final thing, looks good otherwise.

+++ b/salsa_commerce.module
@@ -483,6 +553,21 @@ function salsa_commerce_commerce_checkout_complete($order) {
     salsa_commerce_save_donation($order, $donation_line_item);
+    $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $donation_line_item);
+
+    // Order was completed so user is allowed to begin a new order now.
+    if ($donate_page = $line_item_wrapper->salsa_donate_page->value()) {
+      $order_key = 'donate_page:' . $donate_page->donate_page_KEY;
+    }
+    elseif ($supporter_my_donate_page = $line_item_wrapper->salsa_supporter_my_donate_page->value()) {
+      $order_key = 'my_donate_page:' . $supporter_my_donate_page->supporter_my_donate_page_KEY;
+    }
+    unset($_SESSION['salsa_commerce'][$order_key]);
+  }

I think just looping over the list and deleting the one with the current order ID whould be simpler.

then you can also move it out of the line item loop.

s_leu’s picture

Status: Needs work » Needs review
StatusFileSize
new0 bytes
new7.93 KB

Done.

  • Berdir committed 77af0cc on 7.x-1.x authored by s_leu
    Issue #2689007 by s_leu: Prevent creation of multiple orders
    
berdir’s picture

Status: Needs review » Fixed

Thanks, committed.

Status: Fixed » Closed (fixed)

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