Merge pull request #3626 from yashodha/CRM-14670
[civicrm-core.git] / CRM / Contribute / Form / Contribution / Confirm.php
index 67287c1d4db414fa697a78f6b7ca29c95e4c5e18..c8cec31f3065b2cf00c4b2e42abab442d55f696d 100644 (file)
@@ -254,42 +254,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
       $this->_useForMember = $this->get('useForMember');
 
       if (isset($this->_params['amount'])) {
-        $priceField = new CRM_Price_DAO_PriceField();
-        $priceField->price_set_id = $this->_params['priceSetId'];
-        $priceField->orderBy('weight');
-        $priceField->find();
-        $contriPriceId = NULL;
-        $isQuickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_params['priceSetId'], 'is_quick_config');
-        while ($priceField->fetch()) {
-          if ($priceField->name == "contribution_amount") {
-            $contriPriceId = $priceField->id;
-          }
-          if ($isQuickConfig && !empty($this->_params["price_{$priceField->id}"])) {
-            if ($this->_values['fee'][$priceField->id]['html_type'] != 'Text') {
-            $this->_params['amount_level'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue',
-              $this->_params["price_{$priceField->id}"], 'label');
-            }
-            if ($priceField->name == "membership_amount") {
-              $this->_params['selectMembership'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue',
-                $this->_params["price_{$priceField->id}"], 'membership_type_id');
-            }
-          } // if separate payment we set contribution amount to be null, so that it will not show contribution amount same as membership amount.
-          elseif ((CRM_Utils_Array::value('is_separate_payment', $this->_membershipBlock)) && !empty($this->_values['fee'][$priceField->id]) && ($this->_values['fee'][$priceField->id]['name'] == "other_amount")
-              && CRM_Utils_Array::value("price_{$contriPriceId}", $this->_params) < 1 && empty($this->_params["price_{$priceField->id}"])) {
-              $this->_params['amount'] = null;
-          }
-
-          // Fix for CRM-14375 - If we are using separate payments and "no
-          // thank you" is selected for the additional contribution, set
-          // contribution amount to be null, so that it will not show
-          // contribution amount same as membership amount.
-          if ($this->_membershipBlock['is_separate_payment']
-            && CRM_Utils_Array::value('name', $this->_values['fee'][$priceField->id]) == 'contribution_amount'
-            && CRM_Utils_Array::value("price_{$priceField->id}", $this->_params) == '-1'
-          ) {
-            $this->_params['amount'] = null;
-          }
-        }
+        $this->setFormAmountFields($this->_params['priceSetId']);
       }
       $this->_params['currencyID'] = $config->defaultCurrency;
       $this->_params['payment_action'] = 'Sale';
@@ -439,7 +404,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
 
       $this->_params['is_recur'] = $this->_values['is_recur'] = 1;
       // check if price set is not quick config
-      if (!empty($this->_params['priceSetId']) && !$isQuickConfig) {
+      if (!empty($this->_params['priceSetId']) && !CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_params['priceSetId'], 'is_quick_config')) {
         list($this->_params['frequency_interval'], $this->_params['frequency_unit']) = CRM_Price_BAO_PriceSet::getRecurDetails($this->_params['priceSetId']);
       }
       else {
@@ -689,20 +654,14 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     // fix currency ID
     $this->_params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency;
 
-    $premiumParams = $membershipParams = $params = $this->_params;
-
     //carry payment processor id.
     if ($paymentProcessorId = CRM_Utils_Array::value('id', $this->_paymentProcessor)) {
       $this->_params['payment_processor_id'] = $paymentProcessorId;
-      foreach (array(
-        'premiumParams', 'membershipParams', 'tempParams', 'params') as $p) {
-        ${$p}['payment_processor_id'] = $paymentProcessorId;
-      }
     }
     if (!empty($params['image_URL'])) {
       CRM_Contact_BAO_Contact::processImageParams($params);
     }
-
+    $premiumParams = $membershipParams = $params = $this->_params;
     $fields = array('email-Primary' => 1);
 
     // get the add to groups
@@ -943,7 +902,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
         $membershipParams['cms_contactID'] = $contactID;
       }
 
-      //inherit campaign from contirb page.
+      //inherit campaign from contribution page.
       if (!array_key_exists('campaign_id', $membershipParams)) {
         $membershipParams['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values);
       }
@@ -999,17 +958,18 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
       }
       if (!empty($membershipParams['selectMembership'])) {
         // CRM-12233
+        $membershipLineItems = array();
         if ($this->_separateMembershipPayment && $this->_values['amount_block_is_active']) {
           foreach ($this->_values['fee'] as $key => $feeValues) {
-            if ($feeValues['name'] == 'membership_amount') {
+             if ($feeValues['name'] == 'membership_amount') {
               $fieldId = $this->_params['price_' . $key];
-              $this->_memLineItem[$this->_priceSetId][$fieldId] = $this->_lineItem[$this->_priceSetId][$fieldId];
+              $membershipLineItems[$this->_priceSetId][$fieldId] = $this->_lineItem[$this->_priceSetId][$fieldId];
               unset($this->_lineItem[$this->_priceSetId][$fieldId]);
               break;
             }
           }
         }
-        $this->processMembership($membershipParams, $contactID, $customFieldsFormatted, $fieldTypes, $premiumParams);
+        $this->processMembership($membershipParams, $contactID, $customFieldsFormatted, $fieldTypes, $premiumParams, $membershipLineItems);
         if (!$this->_amount > 0.0 || !$membershipParams['amount']) {
           // we need to explicitly create a CMS user in case of free memberships
           // since it is done under processConfirm for paid memberships
@@ -1199,17 +1159,18 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     $contactID,
     $financialType,
     $pending,
-    $online
+    $online,
+    $isTest,
+    $lineItems
   ) {
     $transaction = new CRM_Core_Transaction();
-    $recurringContributionID =  $contribSoftContactId = $addressID = NULL;
+    $contribSoftContactId = $addressID = NULL;
 
     // add these values for the recurringContrib function ,CRM-10188
     $params['financial_type_id'] = $financialType->id;
 
     //create an contribution address
-    if (
-      $form->_contributeMode != 'notify' && empty($params['is_pay_later']) && !empty($form->_values['is_monetary'])) {
+    if ($form->_contributeMode != 'notify' && empty($params['is_pay_later']) && !empty($form->_values['is_monetary'])) {
       $addressID = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
     }
 
@@ -1731,23 +1692,22 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
   }
 
   /**
-   * @param $membershipParams
-   * @param $contactID
-   * @param $customFieldsFormatted
-   * @param $fieldTypes
-   * @param $premiumParams
+   * @param array $membershipParams
+   * @param integer $contactID
+   * @param array $customFieldsFormatted
+   * @param array $fieldTypes
+   * @param array $premiumParams
+   * @param array $membershipLineItems line items specifically relating to memberships
    */
-  public function processMembership($membershipParams, $contactID, $customFieldsFormatted, $fieldTypes, $premiumParams)
-  {
+  public function processMembership($membershipParams, $contactID, $customFieldsFormatted, $fieldTypes, $premiumParams, $membershipLineItems) {
     try {
+      $membershipTypeID = (array) $membershipParams['selectMembership'];
 
-      $singleMembershipTypeID = $membershipTypeID = $membershipParams['selectMembership'];
-      if (is_array($membershipTypeID) && count($membershipTypeID) == 1) {
-        $singleMembershipTypeID = $membershipTypeID[0];
-      }
+      $membershipTypes = CRM_Member_BAO_Membership::buildMembershipTypeValues($this);
+
+      $membershipType = empty($membershipTypes) ? array() : reset($membershipTypes);
+      $this->assign('membership_name', CRM_Utils_Array::value('name', $membershipType));
 
-      $membershipDetails = CRM_Member_BAO_Membership::buildMembershipTypeValues($this, $singleMembershipTypeID);
-      $this->assign('membership_name', CRM_Utils_Array::value('name', $membershipDetails));
       $isPaidMembership = FALSE;
       if($this->_amount > 0.0 && $membershipParams['amount']) {
         //amount must be greater than zero for
@@ -1758,8 +1718,16 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
       }
       $isProcessSeparateMembershipTransaction = $this->isSeparateMembershipTransaction($this->_id, $this->_values['amount_block_is_active']);
 
+      if ($this->_values['amount_block_is_active']) {
+        $contributionTypeId = $this->_values['financial_type_id'];
+      }
+      else {
+        $contributionTypeId = CRM_Utils_Array::value('financial_type_id', $membershipType, CRM_Utils_Array::value('financial_type_id' ,$membershipParams));
+      }
+
       CRM_Member_BAO_Membership::postProcessMembership($membershipParams, $contactID,
-        $this, $premiumParams, $customFieldsFormatted, $fieldTypes, $membershipDetails,  $membershipTypeID, $isPaidMembership, $this->_membershipId, $isProcessSeparateMembershipTransaction
+        $this, $premiumParams, $customFieldsFormatted, $fieldTypes, $membershipType,  $membershipTypeID, $isPaidMembership, $this->_membershipId, $isProcessSeparateMembershipTransaction, $contributionTypeId,
+        $membershipLineItems
       );
       $this->assign('membership_assign', TRUE);
       $this->set('membershipTypeID', $membershipParams['selectMembership']);
@@ -1788,4 +1756,114 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     }
     return FALSE;
   }
+
+  /**
+   * This function sets the fields
+   * - $this->_params['amount_level']
+   * - $this->_params['selectMembership']
+   * And under certain circumstances sets
+   * $this->_params['amount'] = null;
+   *
+   * @param $priceSetID
+   *
+   * @internal param $isQuickConfig
+   * @internal param $priceField
+   */
+  public function setFormAmountFields($priceSetID) {
+    $isQuickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_params['priceSetId'], 'is_quick_config');
+    $priceField = new CRM_Price_DAO_PriceField();
+    $priceField->price_set_id = $priceSetID;
+    $priceField->orderBy('weight');
+    $priceField->find();
+
+    while ($priceField->fetch()) {
+      $paramWeDoNotUnderstand = NULL;
+      if ($priceField->name == "contribution_amount") {
+        $paramWeDoNotUnderstand = $priceField->id;
+      }
+      if ($isQuickConfig && !empty($this->_params["price_{$priceField->id}"])) {
+        if ($this->_values['fee'][$priceField->id]['html_type'] != 'Text') {
+          $this->_params['amount_level'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue',
+            $this->_params["price_{$priceField->id}"], 'label');
+        }
+        if ($priceField->name == "membership_amount") {
+          $this->_params['selectMembership'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue',
+            $this->_params["price_{$priceField->id}"], 'membership_type_id');
+        }
+      } // if separate payment we set contribution amount to be null, so that it will not show contribution amount same as membership amount.
+      // @todo - this needs more documentation - it appears the setting to null is tied up with separate membership payments
+      // but the circumstances are very confusing. Many of these conditions are repeated in the next conditional
+      // so we should merge them together
+      // the quick config seems like a red-herring - if this is about a separate membership payment then there
+      // are 2 types of line items - membership ones & non-membership ones - regardless of whether quick config is set
+      elseif (
+        CRM_Utils_Array::value('is_separate_payment', $this->_membershipBlock)
+        && !empty($this->_values['fee'][$priceField->id])
+        && ($this->_values['fee'][$priceField->id]['name'] == "other_amount")
+        && CRM_Utils_Array::value("price_{$paramWeDoNotUnderstand}", $this->_params) < 1
+        && empty($this->_params["price_{$priceField->id}"])
+      ) {
+        $this->_params['amount'] = null;
+      }
+
+      // Fix for CRM-14375 - If we are using separate payments and "no
+      // thank you" is selected for the additional contribution, set
+      // contribution amount to be null, so that it will not show
+      // contribution amount same as membership amount.
+      //@todo - merge with section above
+      if ($this->_membershipBlock['is_separate_payment']
+        && CRM_Utils_Array::value('name', $this->_values['fee'][$priceField->id]) == 'contribution_amount'
+        && CRM_Utils_Array::value("price_{$priceField->id}", $this->_params) == '-1'
+      ) {
+        $this->_params['amount'] = null;
+      }
+    }
+  }
+
+  /**
+   * Static submit function allowing tests (& api access although this is being built slowly)
+   * @param $params
+   */
+  static function submit($params) {
+    $form = new CRM_Contribute_Form_Contribution_Confirm();
+    $form->_id = $params['id'];
+    CRM_Contribute_BAO_ContributionPage::setValues($form->_id, $form->_values);
+    $form->_separateMembershipPayment = CRM_Contribute_BAO_ContributionPage::getIsMembershipPayment($form->_id);
+    //this way the mocked up controller ignores the session stuff
+    $_SERVER['REQUEST_METHOD'] = 'GET';
+    $form->controller = new CRM_Contribute_Controller_Contribution();
+    $params['invoiceID'] = md5(uniqid(rand(), TRUE));
+    $paramsProcessedForForm = $form->_params = self::getFormParams($params['id'], $params);
+    $form->_amount = $params['amount'];
+
+
+    $priceSetID = $form->_params['priceSetId'] = $paramsProcessedForForm['price_set_id'];
+    $priceFields = CRM_Price_BAO_PriceSet::getSetDetail($priceSetID);
+    $priceSetFields = reset($priceFields);
+    $form->_values['fee'] = $priceSetFields['fields'];
+    $form->_priceSetId = $priceSetID;
+    $form->setFormAmountFields($priceSetID);
+    $priceFields = $priceFields[$priceSetID]['fields'];
+    CRM_Price_BAO_PriceSet::processAmount($priceFields, $paramsProcessedForForm, $lineItems, 'civicrm_contribution');
+    $form->_lineItem = array($priceSetID => $lineItems);
+    $form->postProcess();
+  }
+
+  /**
+   * Helper function for static submit function - set relevant params - help us to build up an array that we can pass in
+   * @param $id
+   * @param array $params
+   *
+   * @return array
+   * @throws CiviCRM_API3_Exception
+   */
+  static function getFormParams($id, array $params) {
+    if(!isset($params['is_pay_later'])) {
+      $params['is_pay_later'] = civicrm_api3('contribution_page', 'getvalue', array('id' => $id, 'return' => 'is_pay_later'));
+    }
+    if(empty($params['price_set_id'])) {
+      $params['price_set_id'] = CRM_Price_BAO_PriceSet::getFor('civicrm_contribution_page', $params['id']);
+    }
+    return $params;
+  }
 }