Merge pull request #3626 from yashodha/CRM-14670
[civicrm-core.git] / CRM / Contribute / Form / Contribution / Confirm.php
index 9e35636e810606ac88841496a1b6e90135dd6354..c8cec31f3065b2cf00c4b2e42abab442d55f696d 100644 (file)
@@ -55,6 +55,112 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
    */
   public $_contributionID;
 
+  /**
+   * Set the parameters to be passed to contribution create function
+   *
+   * @param array $params
+   * @param integer $contactID
+   * @param $financialTypeID
+   * @param $online
+   * @param $contributionPageId
+   * @param $nonDeductibleAmount
+   * @param $campaignId
+   *
+   * @param $isMonetary
+   *
+   * @param $pending
+   * @param $paymentProcessorOutcome
+   * @param $receiptDate
+   *
+   * @param $recurringContributionID
+   * @param $isTest
+   *
+   * @param $addressID
+   *
+   * @param $softCreditToID
+   *
+   * @param $lineItems
+   *
+   * @internal param $financialType
+   * @return array
+   */
+  public static function getContributionParams($params, $contactID, $financialTypeID, $online, $contributionPageId, $nonDeductibleAmount, $campaignId, $isMonetary, $pending,
+    $paymentProcessorOutcome, $receiptDate, $recurringContributionID, $isTest, $addressID, $softCreditToID, $lineItems)
+  {
+    $contributionParams = array(
+      'contact_id' => $contactID,
+      'financial_type_id' => $financialTypeID,
+      'contribution_page_id' => $contributionPageId,
+      'receive_date' => (CRM_Utils_Array::value('receive_date', $params)) ? CRM_Utils_Date::processDate($params['receive_date']) : date('YmdHis'),
+      'non_deductible_amount' => $nonDeductibleAmount,
+      'total_amount' => $params['amount'],
+      'amount_level' => CRM_Utils_Array::value('amount_level', $params),
+      'invoice_id' => $params['invoiceID'],
+      'currency' => $params['currencyID'],
+      'source' =>
+        (!$online || !empty($params['source'])) ?
+          CRM_Utils_Array::value('source', $params) :
+          CRM_Utils_Array::value('description', $params),
+      'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
+      //configure cancel reason, cancel date and thankyou date
+      //from 'contribution' type profile if included
+      'cancel_reason' => CRM_Utils_Array::value('cancel_reason', $params, 0),
+      'cancel_date' =>
+        isset($params['cancel_date']) ?
+          CRM_Utils_Date::format($params['cancel_date']) :
+          NULL,
+      'thankyou_date' =>
+        isset($params['thankyou_date']) ?
+          CRM_Utils_Date::format($params['thankyou_date']) :
+          NULL,
+      'campaign_id' => $campaignId,
+      'is_test' => $isTest,
+      'address_id' => $addressID,
+      //setting to make available to hook - although seems wrong to set on form for BAO hook availability
+      'soft_credit_to' => $softCreditToID,
+      'line_item' => $lineItems
+    );
+    if (!$online && isset($params['thankyou_date'])) {
+      $contributionParam['thankyou_date'] = $params['thankyou_date'];
+    }
+    if (!$online || $isMonetary) {
+      if (empty($params['is_pay_later'])) {
+        $contributionParams['payment_instrument_id'] = 1;
+      }
+    }
+    if (!$pending && $paymentProcessorOutcome) {
+      $contributionParams += array(
+        'fee_amount' => CRM_Utils_Array::value('fee_amount', $paymentProcessorOutcome),
+        'net_amount' => CRM_Utils_Array::value('net_amount', $paymentProcessorOutcome, $params['amount']),
+        'trxn_id' => $paymentProcessorOutcome['trxn_id'],
+        'receipt_date' => $receiptDate,
+        // also add financial_trxn details as part of fix for CRM-4724
+        'trxn_result_code' => CRM_Utils_Array::value('trxn_result_code', $paymentProcessorOutcome),
+        'payment_processor' => CRM_Utils_Array::value('payment_processor', $paymentProcessorOutcome),
+      );
+    }
+
+    // CRM-4038: for non-en_US locales, CRM_Contribute_BAO_Contribution::add() expects localised amounts
+    $contributionParams['non_deductible_amount'] = trim(CRM_Utils_Money::format($contributionParams['non_deductible_amount'], ' '));
+    $contributionParams['total_amount'] = trim(CRM_Utils_Money::format($contributionParams['total_amount'], ' '));
+
+    if ($recurringContributionID) {
+      $contributionParams['contribution_recur_id'] = $recurringContributionID;
+    }
+
+    $contributionParams['contribution_status_id'] = $pending ? 2 : 1;
+    if (isset($contributionParams['invoice_id'])) {
+      $contributionParams['id'] = CRM_Core_DAO::getFieldValue(
+        'CRM_Contribute_DAO_Contribution',
+        $contributionParams['invoice_id'],
+        'id',
+        'invoice_id'
+      );
+    }
+
+    return $contributionParams;
+  }
+
   /**
    * Function to set variables up before form is built
    *
@@ -148,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';
@@ -333,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 {
@@ -583,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
@@ -837,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);
       }
@@ -893,25 +958,25 @@ 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;
             }
           }
         }
-
-        try {
-          CRM_Member_BAO_Membership::postProcessMembership($membershipParams, $contactID,
-            $this, $premiumParams, $customFieldsFormatted,
-            $fieldTypes
+        $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
+          CRM_Contribute_BAO_Contribution_Utils::createCMSUser($membershipParams,
+            $membershipParams['cms_contactID'],
+            'email-' . $this->_bltID
           );
-        } catch (CRM_Core_Exception $e) {
-          CRM_Core_Session::singleton()->setStatus($e->getMessage());
-          CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact', "_qf_Main_display=true&qfKey={$this->_params['qfKey']}"));
         }
       }
     }
@@ -953,6 +1018,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
    * @access public
    */
   public function postProcessPremium($premiumParams, $contribution) {
+    $hour = $minute = $second = 0;
     // assigning Premium information to receipt tpl
     $selectProduct = CRM_Utils_Array::value('selectProduct', $premiumParams);
     if ($selectProduct &&
@@ -1071,14 +1137,18 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
    * Process the contribution
    *
    * @param $form
-   * @param $params
-   * @param $result
-   * @param $contactID
-   * @param $contributionType
-   * @param bool $deductibleMode
+   * @param array $params
+   * @param array $result
+   * @param integer $contactID
+   * @param CRM_Financial_DAO_FinancialType $financialType
    * @param bool $pending
    * @param bool $online
    *
+   * @param bool $isTest
+   * @param array $lineItems
+   *
+   * @throws Exception
+   * @internal param bool $deductibleMode
    * @return CRM_Contribute_DAO_Contribution
    * @access public
    */
@@ -1087,17 +1157,23 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     $params,
     $result,
     $contactID,
-    $contributionType,
-    $deductibleMode = TRUE,
-    $pending        = FALSE,
-    $online         = TRUE
+    $financialType,
+    $pending,
+    $online,
+    $isTest,
+    $lineItems
   ) {
     $transaction = new CRM_Core_Transaction();
-    $className   = get_class($form);
-    $recurringContributionID = NULL;
+    $contribSoftContactId = $addressID = NULL;
 
     // add these values for the recurringContrib function ,CRM-10188
-    $params['financial_type_id'] = $contributionType->id;
+    $params['financial_type_id'] = $financialType->id;
+
+    //create an contribution address
+    if ($form->_contributeMode != 'notify' && empty($params['is_pay_later']) && !empty($form->_values['is_monetary'])) {
+      $addressID = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
+    }
+
     //@todo - this is being set from the form to resolve CRM-10188 - an
     // eNotice caused by it not being set @ the front end
     // however, we then get it being over-written with null for backend contributions
@@ -1107,7 +1183,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     if(!isset($params['is_email_receipt'])){
       $params['is_email_receipt'] = CRM_Utils_Array::value( 'is_email_receipt', $form->_values );
     }
-    $recurringContributionID = self::processRecurringContribution($form, $params, $contactID, $contributionType, $online);
+    $recurringContributionID = self::processRecurringContribution($form, $params, $contactID, $financialType, $online);
 
     // CRM-11885
     // if non_deductible_amount exists i.e. Additional Details fieldset was opened [and staff typed something] -> keep it.
@@ -1118,7 +1194,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     // $contributionType->is_deductible and whether there is a product (premium).
     else {
       //if ($contributionType->is_deductible && $deductibleMode) {
-      if ($contributionType->is_deductible) {
+      if ($financialType->is_deductible) {
         if ($online && isset($params['selectProduct'])) {
           $selectProduct = CRM_Utils_Array::value('selectProduct', $params);
         }
@@ -1173,94 +1249,6 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
       $campaignId = CRM_Utils_Array::value('campaign_id', $params);
     }
 
-    // first create the contribution record
-    $contribParams = array(
-      'contact_id' => $contactID,
-      'financial_type_id'  => $contributionType->id,
-      'contribution_page_id' => $contributionPageId,
-      'receive_date' => (CRM_Utils_Array::value('receive_date', $params)) ? CRM_Utils_Date::processDate($params['receive_date']) : date('YmdHis'),
-      'non_deductible_amount' => $nonDeductibleAmount,
-      'total_amount' => $params['amount'],
-      'amount_level' => CRM_Utils_Array::value('amount_level', $params),
-      'invoice_id' => $params['invoiceID'],
-      'currency' => $params['currencyID'],
-      'source' =>
-      (!$online || !empty($params['source'])) ?
-      CRM_Utils_Array::value('source', $params) :
-      CRM_Utils_Array::value('description', $params),
-      'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
-      //configure cancel reason, cancel date and thankyou date
-      //from 'contribution' type profile if included
-      'cancel_reason' => CRM_Utils_Array::value('cancel_reason', $params, 0),
-      'cancel_date' =>
-      isset($params['cancel_date']) ?
-      CRM_Utils_Date::format($params['cancel_date']) :
-      NULL,
-      'thankyou_date' =>
-      isset($params['thankyou_date']) ?
-      CRM_Utils_Date::format($params['thankyou_date']) :
-      NULL,
-      'campaign_id' => $campaignId,
-    );
-
-    if (!$online && isset($params['thankyou_date'])) {
-      $contribParams['thankyou_date'] = $params['thankyou_date'];
-    }
-
-    if (!$online || $form->_values['is_monetary']) {
-      if (empty($params['is_pay_later'])) {
-        $contribParams['payment_instrument_id'] = 1;
-      }
-    }
-
-    if (!$pending && $result) {
-      $contribParams += array(
-        'fee_amount' => CRM_Utils_Array::value('fee_amount', $result),
-        'net_amount' => CRM_Utils_Array::value('net_amount', $result, $params['amount']),
-        'trxn_id' => $result['trxn_id'],
-        'receipt_date' => $receiptDate,
-        // also add financial_trxn details as part of fix for CRM-4724
-        'trxn_result_code' => CRM_Utils_Array::value('trxn_result_code', $result),
-        'payment_processor' => CRM_Utils_Array::value('payment_processor', $result),
-      );
-    }
-
-    if ($recurringContributionID) {
-      $contribParams['contribution_recur_id'] = $recurringContributionID;
-    }
-
-    $contribParams['contribution_status_id'] = $pending ? 2 : 1;
-
-    $contribParams['is_test'] = 0;
-    if ($form->_mode == 'test') {
-      $contribParams['is_test'] = 1;
-    }
-
-    $ids = array();
-    if (isset($contribParams['invoice_id'])) {
-      $contribID = CRM_Core_DAO::getFieldValue(
-        'CRM_Contribute_DAO_Contribution',
-        $contribParams['invoice_id'],
-        'id',
-        'invoice_id'
-      );
-      if (isset($contribID)) {
-        $ids['contribution'] = $contribID;
-        $contribParams['id'] = $contribID;
-      }
-    }
-
-
-    //create an contribution address
-    if (
-      $form->_contributeMode != 'notify' && empty($params['is_pay_later']) && !empty($form->_values['is_monetary'])) {
-      $contribParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
-    }
-
-    // CRM-4038: for non-en_US locales, CRM_Contribute_BAO_Contribution::add() expects localised amounts
-    $contribParams['non_deductible_amount'] = trim(CRM_Utils_Money::format($contribParams['non_deductible_amount'], ' '));
-    $contribParams['total_amount'] = trim(CRM_Utils_Money::format($contribParams['total_amount'], ' '));
-
     // Prepare soft contribution due to pcp or Submit Credit / Debit Card Contribution by admin.
     if (!empty($params['pcp_made_through_id']) || !empty($params['soft_credit_to'])) {
       // if its due to pcp
@@ -1277,13 +1265,15 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
 
       // Pass these details onto with the contribution to make them
       // available at hook_post_process, CRM-8908
-      $contribParams['soft_credit_to'] = $params['soft_credit_to'] = $contribSoftContactId;
+      $params['soft_credit_to'] = $contribSoftContactId;
     }
 
     if (isset($params['amount'])) {
-      $contribParams['line_item'] = $form->_lineItem;
-      //add contribution record
-      $contribution = CRM_Contribute_BAO_Contribution::add($contribParams, $ids);
+      $contribParams = self::getContributionParams(
+        $params, $contactID, $financialType->id, $online, $contributionPageId, $nonDeductibleAmount, $campaignId, $form->_values['is_monetary'], $pending, $result, $receiptDate,
+        $recurringContributionID, $isTest, $addressID, $contribSoftContactId, $lineItems
+      );
+      $contribution = CRM_Contribute_BAO_Contribution::add($contribParams);
       if (is_a($contribution, 'CRM_Core_Error')) {
         $message = CRM_Core_Error::getMessages($contribution);
         CRM_Core_Error::fatal($message);
@@ -1700,4 +1690,180 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
 
     return $params;
   }
+
+  /**
+   * @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, $membershipLineItems) {
+    try {
+      $membershipTypeID = (array) $membershipParams['selectMembership'];
+
+      $membershipTypes = CRM_Member_BAO_Membership::buildMembershipTypeValues($this);
+
+      $membershipType = empty($membershipTypes) ? array() : reset($membershipTypes);
+      $this->assign('membership_name', CRM_Utils_Array::value('name', $membershipType));
+
+      $isPaidMembership = FALSE;
+      if($this->_amount > 0.0 && $membershipParams['amount']) {
+        //amount must be greater than zero for
+        //adding contribution record  to contribution table.
+        //this condition arises when separate membership payment is
+        //enabled and contribution amount is not selected. fix for CRM-3010
+        $isPaidMembership = TRUE;
+      }
+      $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, $membershipType,  $membershipTypeID, $isPaidMembership, $this->_membershipId, $isProcessSeparateMembershipTransaction, $contributionTypeId,
+        $membershipLineItems
+      );
+      $this->assign('membership_assign', TRUE);
+      $this->set('membershipTypeID', $membershipParams['selectMembership']);
+    }
+    catch (CRM_Core_Exception $e) {
+      CRM_Core_Session::singleton()->setStatus($e->getMessage());
+      CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact', "_qf_Main_display=true&qfKey={$this->_params['qfKey']}"));
+    }
+  }
+
+  /**
+   * Are we going to do 2 financial transactions?
+   * ie the membership block supports a separate transactions AND the contribution form has been configured for a contribution
+   * transaction AND a membership transaction AND the payment processor supports double financial transactions (ie. NOT doTransferPayment style)
+   *
+   *
+   * @param integer $formID
+   * @param bool $amountBlockActiveOnForm
+   *
+   * @return bool
+   */
+  public function isSeparateMembershipTransaction($formID, $amountBlockActiveOnForm) {
+    $memBlockDetails = CRM_Member_BAO_Membership::getMembershipBlock($formID);
+    if (!empty($memBlockDetails['is_separate_payment']) && $amountBlockActiveOnForm) {
+      return TRUE;
+    }
+    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;
+  }
 }