From 689c6fb52a9633ae86187dce87753932653f4c58 Mon Sep 17 00:00:00 2001
From: Seamus Lee <seamuslee001@gmail.com>
Date: Mon, 28 Mar 2022 18:22:30 +1100
Subject: [PATCH] Shift contribution create code into own function so can be
 called at the end of transaction to ensure the correct recurring solicit and
 sub solicit codes are stored when IPN is processed from Auth.net

---
 ehc.php | 140 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 78 insertions(+), 62 deletions(-)

diff --git a/ehc.php b/ehc.php
index ebb51d1..160965d 100644
--- a/ehc.php
+++ b/ehc.php
@@ -236,73 +236,89 @@ function ehc_civicrm_post($op, $objectName, $objectId, &$objectRef) {
       }
     }
     if ($objectName == "Contribution") {
-      $contribution = civicrm_api3('Contribution', 'getsingle', array(
-        'return' => array("financial_type_id", "non_deductible_amount", "custom_256"),
-        'id' => $objectId,
-      ));
-      $org = civicrm_api3('EntityFinancialAccount', 'getsingle', array(
-        'return' => array("financial_account_id.contact_id.legal_name", "financial_account_id.contact_id.organization_name"),
-        'entity_table' => "civicrm_financial_type",
-        'entity_id' => $contribution["financial_type_id"],
-        'options' => array('limit' => 1),
-      ));
-      // Insert the recurring custom field value.
-      if (!empty($objectRef->contribution_recur_id)) {
-	civicrm_api3('Contribution', 'create', array('id' => $objectRef->id, 'custom_268' => 1, 'custom_269' => 'Recurring'));
-	// Set the Recurring Solicitation fields as well as they will be used later on.
-	civicrm_api3('ContributionRecur', 'create', ['custom_34' => 'REC', 'custom_35' => 10, 'id' => $objectRef->contribution_recur_id]);
+      if (CRM_Core_Transaction::isActive()) {
+        CRM_Core_Transaction::addCallback(CRM_Core_Transaction::PHASE_POST_COMMIT, 'ehc_contribution_post_callback', [$op, $objectName, $objectId, $objectRef]);
       }
       else {
-        $ftName = CRM_Contribute_PseudoConstant::financialType($objectRef->financial_type_id);
-        $sc = CRM_Core_Smarty::singleton()->get_template_vars('sc');
-        $ssc = CRM_Core_Smarty::singleton()->get_template_vars('ssc');
-        civicrm_api3('Contribution', 'create', array('id' => $objectRef->id, 'custom_269' => getFinanceColumn($ftName, $sc, $ssc)));
-      }
-      CRM_Core_Smarty::singleton()->assign("financialorg", $org["financial_account_id.contact_id.legal_name"]);
-      CRM_Core_Smarty::singleton()->assign("nondeductibleamount", $contribution['non_deductible_amount']);
-      if (!empty($objectRef->contribution_page_id) || !empty($objectRef->contribution_recur_id)) {
-        $customColumns = Civi::cache('ehcCustomColumns')->get('contributionPageColumns');
-        $contriCustomIDs = Civi::cache('ehcCustomColumns')->get('contributionColumns');
-        if (!$customColumns) {
-          $customColumns = getCustomColumnsByEntity('ContributionPage');
-          Civi::cache('ehcCustomColumns')->set('contributionPageColumns', $customColumns);
-        }
-        if (!$contriCustomIDs) {
-          $contriCustomIDs = getCustomColumnsByEntity('Contribution', TRUE);
-          Civi::cache('ehcCustomColumns')->set('contributionColumns', $contriCustomIDs);
-        }
-        if (!empty($customColumns) && !empty($contriCustomIDs)) {
-          // First check if solicit and sub solicit set in Recurring Profile.
-          if (!empty($objectRef->contribution_recur_id)) {
-            $customRecurColumns = getCustomColumnsByEntity('ContributionRecur');
-            $tablename = key($customRecurColumns);
-            $result = CRM_Core_DAO::executeQuery(sprintf("SELECT %s FROM %s WHERE entity_id = %d ",implode(',', $customRecurColumns[$tablename]), $tablename, $objectRef->contribution_recur_id))->fetchAll();
-          }
-          if (empty($result) && !empty($objectRef->contribution_page_id)) {
-            $tablename = key($customColumns);
-            $result = CRM_Core_DAO::executeQuery(sprintf("SELECT %s FROM %s WHERE entity_id = %d ",implode(',', $customColumns[$tablename]), $tablename, $objectRef->contribution_page_id))->fetchAll();
-          }
-          elseif (!empty($result)) {
-            // Assign the found recur contribution columns to the $customColumns variable for use further down.
-            $customColumns = $customRecurColumns;
-          }
-          $params = ['id' => $objectRef->id];
-          if (!empty($result)) {
-            foreach ($result as $value) {
-              foreach ($customColumns as $tableName => $keys) {
-                $params['custom_' . $contriCustomIDs['Contribution']['sc']] = $value[$keys['sc']];
-                $params['custom_' . $contriCustomIDs['Contribution']['ssc']] = $value[$keys['ssc']];
-                // Add finance team columns.
-                $ftName = CRM_Contribute_PseudoConstant::financialType($objectRef->financial_type_id);
-                $sc = CRM_Core_DAO::singleValueQuery("SELECT name FROM civicrm_option_value WHERE value = '" . $values[$keys['sc']] . "' AND option_group_id = 96");
-                $ssc = CRM_Core_DAO::singleValueQuery("SELECT name FROM civicrm_option_value WHERE value = '" . $values[$keys['ssc']] . "' AND option_group_id = 97");
-                $params['custom_269'] = getFinanceColumn($ftName, $sc, $ssc);
-              }
-            }
+        ehc_contribution_post_callback($op, $objectName, $objectId, $objectRef);
+      }
+    }
+  }
+}
+
+/**
+ * Function Triggered when post hook on a contribution.create is called
+ * @param string $op
+ * @param string $objectName
+ * @param int $objectId
+ * @param \CRM_Contribute_DAO_ContributionObject $objectRef
+ */
+function ehc_contribution_post_callback($op, $objectName, $objectId, $objectRef): void {
+  $contribution = civicrm_api3('Contribution', 'getsingle', array(
+    'return' => array("financial_type_id", "non_deductible_amount", "custom_256"),
+    'id' => $objectId,
+  ));
+  $org = civicrm_api3('EntityFinancialAccount', 'getsingle', array(
+    'return' => array("financial_account_id.contact_id.legal_name", "financial_account_id.contact_id.organization_name"),
+    'entity_table' => "civicrm_financial_type",
+    'entity_id' => $contribution["financial_type_id"],
+    'options' => array('limit' => 1),
+  ));
+  // Insert the recurring custom field value.
+  if (!empty($objectRef->contribution_recur_id)) {
+    civicrm_api3('Contribution', 'create', array('id' => $objectRef->id, 'custom_268' => 1, 'custom_269' => 'Recurring'));
+    // Set the Recurring Solicitation fields as well as they will be used later on.
+    civicrm_api3('ContributionRecur', 'create', ['custom_34' => 'REC', 'custom_35' => 10, 'id' => $objectRef->contribution_recur_id]);
+  }
+  else {
+    $ftName = CRM_Contribute_PseudoConstant::financialType($objectRef->financial_type_id);
+    $sc = CRM_Core_Smarty::singleton()->get_template_vars('sc');
+    $ssc = CRM_Core_Smarty::singleton()->get_template_vars('ssc');
+    civicrm_api3('Contribution', 'create', array('id' => $objectRef->id, 'custom_269' => getFinanceColumn($ftName, $sc, $ssc)));
+  }
+  CRM_Core_Smarty::singleton()->assign("financialorg", $org["financial_account_id.contact_id.legal_name"]);
+  CRM_Core_Smarty::singleton()->assign("nondeductibleamount", $contribution['non_deductible_amount']);
+  if (!empty($objectRef->contribution_page_id) || !empty($objectRef->contribution_recur_id)) {
+    $customColumns = Civi::cache('ehcCustomColumns')->get('contributionPageColumns');
+    $contriCustomIDs = Civi::cache('ehcCustomColumns')->get('contributionColumns');
+    if (!$customColumns) {
+      $customColumns = getCustomColumnsByEntity('ContributionPage');
+      Civi::cache('ehcCustomColumns')->set('contributionPageColumns', $customColumns);
+    }
+    if (!$contriCustomIDs) {
+      $contriCustomIDs = getCustomColumnsByEntity('Contribution', TRUE);
+      Civi::cache('ehcCustomColumns')->set('contributionColumns', $contriCustomIDs);
+    }
+    if (!empty($customColumns) && !empty($contriCustomIDs)) {
+      // First check if solicit and sub solicit set in Recurring Profile.
+      if (!empty($objectRef->contribution_recur_id)) {
+        $customRecurColumns = getCustomColumnsByEntity('ContributionRecur');
+        $tablename = key($customRecurColumns);
+        $result = CRM_Core_DAO::executeQuery(sprintf("SELECT %s FROM %s WHERE entity_id = %d ",implode(',', $customRecurColumns[$tablename]), $tablename, $objectRef->contribution_recur_id))->fetchAll();
+      }
+      if (empty($result) && !empty($objectRef->contribution_page_id)) {
+        $tablename = key($customColumns);
+        $result = CRM_Core_DAO::executeQuery(sprintf("SELECT %s FROM %s WHERE entity_id = %d ",implode(',', $customColumns[$tablename]), $tablename, $objectRef->contribution_page_id))->fetchAll();
+      }
+      elseif (!empty($result)) {
+        // Assign the found recur contribution columns to the $customColumns variable for use further down.
+        $customColumns = $customRecurColumns;
+      }
+      $params = ['id' => $objectRef->id];
+      if (!empty($result)) {
+        foreach ($result as $value) {
+          foreach ($customColumns as $tableName => $keys) {
+            $params['custom_' . $contriCustomIDs['Contribution']['sc']] = $value[$keys['sc']];
+            $params['custom_' . $contriCustomIDs['Contribution']['ssc']] = $value[$keys['ssc']];
+            // Add finance team columns.
+            $ftName = CRM_Contribute_PseudoConstant::financialType($objectRef->financial_type_id);
+            $sc = CRM_Core_DAO::singleValueQuery("SELECT name FROM civicrm_option_value WHERE value = '" . $values[$keys['sc']] . "' AND option_group_id = 96");
+            $ssc = CRM_Core_DAO::singleValueQuery("SELECT name FROM civicrm_option_value WHERE value = '" . $values[$keys['ssc']] . "' AND option_group_id = 97");
+            $params['custom_269'] = getFinanceColumn($ftName, $sc, $ssc);
           }
-          civicrm_api3('Contribution', 'create', $params);
         }
       }
+      civicrm_api3('Contribution', 'create', $params);
     }
   }
 }
-- 
GitLab