CRM-15621 - prevent fatal on payment updates with Auth.net IPN
authorDave Greenberg <dave@civicrm.org>
Wed, 19 Nov 2014 23:23:31 +0000 (15:23 -0800)
committerDave Greenberg <dave@civicrm.org>
Wed, 19 Nov 2014 23:23:31 +0000 (15:23 -0800)
----------------------------------------
* CRM-15621:
  https://issues.civicrm.org/jira/browse/CRM-15621

CRM/Contribute/BAO/Contribution.php
CRM/Core/Payment/BaseIPN.php

index bffeb39cd3e139b8dc9ead66327ad99fc691460c..55b8211ee8143047812c86b0621c92ea325404ef 100644 (file)
@@ -244,21 +244,19 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
    * based on querying the line item table and relevant price field values
    * Note that any one contribution should only be able to have one line item relating to a particular membership
    * type
+   *
    * @param int $membershipTypeID
    *
+   * @param int $contributionID
+   *
    * @return int
    */
-  public function getNumTermsByContributionAndMembershipType($membershipTypeID) {
-    if (!is_numeric($membershipTypeID)) {
-      //precautionary measure - this is being introduced to a mature release hence adding extra checks that
-      // might be removed later
-      return 1;
-    }
-    $numTerms = CRM_Core_DAO::singleValueQuery("
+  public function getNumTermsByContributionAndMembershipType($membershipTypeID, $contributionID) {
+     $numTerms = CRM_Core_DAO::singleValueQuery("
       SELECT membership_num_terms FROM civicrm_line_item li
       LEFT JOIN civicrm_price_field_value v ON li.price_field_value_id = v.id
       WHERE contribution_id = %1 AND membership_type_id = %2",
-      array(1 => array($this->id, 'Integer') , 2 => array($membershipTypeID, 'Integer'))
+      array(1 => array($contributionID, 'Integer') , 2 => array($membershipTypeID, 'Integer'))
     );
     // default of 1 is precautionary
     return empty($numTerms) ? 1 : $numTerms;
index 6d8a807ddef35aa65c34aac7fa4db276cab4c01d..3034ab939a408a91904e013d7b49cc7a2684a5f9 100644 (file)
@@ -104,7 +104,12 @@ class CRM_Core_Payment_BaseIPN {
     if (!$this->loadObjects($input, $ids, $objects, $required, $paymentProcessorID)) {
       return FALSE;
     }
-
+    //the process is that the loadObjects is kind of hacked by loading the objects for the original contribution and then somewhat inconsistently using them for the
+    //current contribution. Here we ensure that the original contribution is available to the complete transaction function
+    //we don't want to fix this in the payment processor classes because we would have to fix all of them - so better to fix somewhere central
+    if (isset($objects['contributionRecur'])) {
+      $objects['first_contribution'] = $objects['contribution'];
+    }
     return TRUE;
   }
 
@@ -335,6 +340,9 @@ class CRM_Core_Payment_BaseIPN {
    */
   function completeTransaction(&$input, &$ids, &$objects, &$transaction, $recur = FALSE) {
     $contribution = &$objects['contribution'];
+
+    $primaryContributionID = isset($contribution->id) ? $contribution->id : $objects['first_contribution']->id;
+
     $memberships = &$objects['membership'];
     if (is_numeric($memberships)) {
       $memberships = array($objects['membership']);
@@ -401,7 +409,7 @@ LIMIT 1;";
             // else fall back to using current membership type
             $dao->free();
 
-            $num_terms = $contribution->getNumTermsByContributionAndMembershipType($membership->membership_type_id);
+            $num_terms = $contribution->getNumTermsByContributionAndMembershipType($membership->membership_type_id, $primaryContributionID);
             if ($currentMembership) {
               /*
                * Fixed FOR CRM-4433