manual merge of fixes for CRM-13981
[civicrm-core.git] / CRM / Contribute / Form / Contribution.php
index b1748f9254367151d33a1b08ff2e1f88f900865d..4db4bdea08db1fbd8a89d6a97e4f32d39c9bc686 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.3                                                |
+ | CiviCRM version 4.4                                                |
  +--------------------------------------------------------------------+
  | Copyright CiviCRM LLC (c) 2004-2013                                |
  +--------------------------------------------------------------------+
@@ -104,14 +104,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
    */
   public $_options;
 
-  /**
-   * stores the honor id
-   *
-   * @var int
-   * @public
-   */
-  public $_honorID = NULL;
-
   /**
    * Store the contribution Type ID
    *
@@ -140,6 +132,11 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
    */
   public $_lineItems;
 
+  /**
+   * @var soft credit info
+   */
+  public $_softCreditInfo;
+
   protected $_formType;
   protected $_cdType;
 
@@ -150,6 +147,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
    * @access public
    */
   public function preProcess() {
+
     //check permission for action.
     if (!CRM_Core_Permission::checkActionPermission('CiviContribute', $this->_action)) {
       CRM_Core_Error::fatal(ts('You do not have permission to access this page'));
@@ -164,6 +162,11 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       return;
     }
 
+    $config = CRM_Core_Config::singleton();
+    $resources = CRM_Core_Resources::singleton();
+    $resources->addScriptFile('civicrm', 'templates/CRM/Contribute/Form/SoftCredit.js');
+    $resources->addSetting(array('monetaryThousandSeparator' => $config->monetaryThousandSeparator));
+
     $this->_formType = CRM_Utils_Array::value('formType', $_GET);
 
     // get price set id.
@@ -223,7 +226,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       return;
     }
 
-    $config = CRM_Core_Config::singleton();
     if (in_array('CiviPledge', $config->enableComponents) && !$this->_formType) {
       $this->preProcessPledge();
     }
@@ -237,7 +239,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     }
 
     // when custom data is included in this page
-    if (CRM_Utils_Array::value('hidden_custom', $_POST)) {
+    if (!empty($_POST['hidden_custom'])) {
       $this->applyCustomData('Contribution', CRM_Utils_Array::value('financial_type_id', $_POST), $this->_id);
     }
 
@@ -248,7 +250,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
         $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_compId);
       }
       else {
-        $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'contribution',1);
+        $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'contribution', 1);
       }
       empty($lineItem) ? NULL : $this->_lineItems[] = $lineItem;
     }
@@ -265,9 +267,8 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
 
       // omitting contactImage from title for now since the summary overlay css doesn't work outside of our crm-container
-      CRM_Utils_System::setTitle(ts('Contribution from') .  ' ' . $displayName);
+      CRM_Utils_System::setTitle(ts('Contribution from') . ' ' . $displayName);
     }
-
   }
 
   function setDefaultValues() {
@@ -280,8 +281,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     //set defaults for pledge payment.
     if ($this->_ppID) {
       $defaults['total_amount'] = CRM_Utils_Array::value('scheduled_amount', $this->_pledgeValues['pledgePayment']);
-      $defaults['honor_type_id'] = CRM_Utils_Array::value('honor_type_id', $this->_pledgeValues);
-      $defaults['honor_contact_id'] = CRM_Utils_Array::value('honor_contact_id', $this->_pledgeValues);
       $defaults['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $this->_pledgeValues);
       $defaults['currency'] = CRM_Utils_Array::value('currency', $this->_pledgeValues);
       $defaults['option_type'] = 1;
@@ -292,38 +291,24 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       return $defaults;
     }
 
+    // set soft credit defaults
+    CRM_Contribute_Form_SoftCredit::setDefaultValues($defaults, $this);
+
     if ($this->_mode) {
       $config = CRM_Core_Config::singleton();
       // set default country from config if no country set
-      if (!CRM_Utils_Array::value("billing_country_id-{$this->_bltID}", $defaults)) {
+      if (empty($defaults["billing_country_id-{$this->_bltID}"])) {
         $defaults["billing_country_id-{$this->_bltID}"] = $config->defaultContactCountry;
       }
 
-      if (!CRM_Utils_Array::value("billing_state_province_id-{$this->_bltID}", $defaults)) {
+      if (empty($defaults["billing_state_province_id-{$this->_bltID}"])) {
         $defaults["billing_state_province_id-{$this->_bltID}"] = $config->defaultContactStateProvince;
       }
 
-      $names = array(
-        'first_name', 'middle_name', 'last_name', "street_address-{$this->_bltID}", "city-{$this->_bltID}",
-        "postal_code-{$this->_bltID}", "country_id-{$this->_bltID}", "state_province_id-{$this->_bltID}",
-        "state_province-{$this->_bltID}", "country-{$this->_bltID}"
-        );
-
-      foreach ($names as $name) {
-        $fields[$name] = 1;
-      }
-
-      if ($this->_contactID) {
-        CRM_Core_BAO_UFGroup::setProfileDefaults($this->_contactID, $fields, $defaults);
-      }
-
-      foreach ($names as $name) {
-        if (!empty($defaults[$name])) {
-          $defaults['billing_' . $name] = $defaults[$name];
-        }
-      }
+      $billingDefaults = $this->getProfileDefaults('Billing', $this->_contactID);
+      $defaults = array_merge($defaults, $billingDefaults);
 
-      // now fix all state country selectors
+      // now fix all state country selectors, set correct state based on country
       CRM_Core_BAO_Address::fixAllStateSelects($this, $defaults);
     }
 
@@ -355,25 +340,12 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       $defaults['financial_type_id'] = $this->_contributionType;
     }
 
-    if (CRM_Utils_Array::value('is_test', $defaults)) {
-      $this->assign('is_test', TRUE);
+    if (empty($defaults['payment_instrument_id'])) {
+      $defaults['payment_instrument_id'] = key(CRM_Core_OptionGroup::values('payment_instrument', FALSE, FALSE, FALSE, 'AND is_default = 1'));
     }
 
-    if (isset($defaults['honor_contact_id'])) {
-      $honorDefault = $ids = array();
-      $this->_honorID = $defaults['honor_contact_id'];
-      $honorType = CRM_Core_PseudoConstant::honor();
-      $idParams = array(
-        'id' => $defaults['honor_contact_id'],
-        'contact_id' => $defaults['honor_contact_id'],
-      );
-      CRM_Contact_BAO_Contact::retrieve($idParams, $honorDefault, $ids);
-
-      $defaults['honor_prefix_id'] = CRM_Utils_Array::value('prefix_id', $honorDefault);
-      $defaults['honor_first_name'] = CRM_Utils_Array::value('first_name', $honorDefault);
-      $defaults['honor_last_name'] = CRM_Utils_Array::value('last_name', $honorDefault);
-      $defaults['honor_email'] = CRM_Utils_Array::value('email', $honorDefault['email'][1]);
-      $defaults['honor_type'] = $honorType[$defaults['honor_type_id']];
+    if (!empty($defaults['is_test'])) {
+      $this->assign('is_test', TRUE);
     }
 
     $this->assign('showOption', TRUE);
@@ -400,14 +372,14 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       $this->assign('email', $this->userEmail);
     }
 
-    if (CRM_Utils_Array::value('is_pay_later', $defaults)) {
+    if (!empty($defaults['is_pay_later'])) {
       $this->assign('is_pay_later', TRUE);
     }
     $this->assign('contribution_status_id', CRM_Utils_Array::value('contribution_status_id', $defaults));
 
     $dates = array('receive_date', 'receipt_date', 'cancel_date', 'thankyou_date');
     foreach ($dates as $key) {
-      if (CRM_Utils_Array::value($key, $defaults)) {
+      if (!empty($defaults[$key])) {
         list($defaults[$key],
           $defaults[$key . '_time']
           ) = CRM_Utils_Date::setDateDefaults(CRM_Utils_Array::value($key, $defaults),
@@ -416,7 +388,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
     }
 
-    if (!$this->_id && !CRM_Utils_Array::value('receive_date', $defaults)) {
+    if (!$this->_id && empty($defaults['receive_date'])) {
       list($defaults['receive_date'],
         $defaults['receive_date_time']
         ) = CRM_Utils_Date::setDateDefaults(NULL, 'activityDateTime');
@@ -433,7 +405,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     $this->assign('totalAmount', CRM_Utils_Array::value('total_amount', $defaults));
 
     //inherit campaign from pledge.
-    if ($this->_ppID && CRM_Utils_Array::value('campaign_id', $this->_pledgeValues)) {
+    if ($this->_ppID && !empty($this->_pledgeValues['campaign_id'])) {
       $defaults['campaign_id'] = $this->_pledgeValues['campaign_id'];
     }
 
@@ -456,7 +428,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     // build price set form.
     $buildPriceSet = FALSE;
     if (empty($this->_lineItems) &&
-      ($this->_priceSetId || CRM_Utils_Array::value('price_set_id', $_POST))
+      ($this->_priceSetId || !empty($_POST['price_set_id']))
     ) {
       $buildPriceSet = TRUE;
       $getOnlyPriceSetElements = TRUE;
@@ -466,7 +438,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
 
       $this->set('priceSetId', $this->_priceSetId);
-      CRM_Price_BAO_Set::buildPriceSet($this);
+      CRM_Price_BAO_PriceSet::buildPriceSet($this);
 
       // get only price set form elements.
       if ($getOnlyPriceSetElements) {
@@ -478,7 +450,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     $showAdditionalInfo = FALSE;
 
-
     $defaults = $this->_values;
     $additionalDetailFields = array(
       'note',
@@ -486,7 +457,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       'invoice_id',
       'non_deductible_amount',
       'fee_amount',
-      'net_amount'
+      'net_amount',
     );
     foreach ($additionalDetailFields as $key) {
       if (!empty($defaults[$key])) {
@@ -495,25 +466,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
     }
 
-    $honorFields = array(
-      'honor_type_id',
-      'honor_prefix_id',
-      'honor_first_name',
-      'honor_lastname',
-      'honor_email',
-    );
-    foreach ($honorFields as $key) {
-      if (!empty($defaults[$key])) {
-        $defaults['hidden_Honoree'] = 1;
-        break;
-      }
-    }
-
-    //check for honoree pane.
-    if ($this->_ppID && CRM_Utils_Array::value('honor_contact_id', $this->_pledgeValues)) {
-      $defaults['hidden_Honoree'] = 1;
-    }
-
     if ($this->_productDAO) {
       if ($this->_productDAO->product_id) {
         $defaults['hidden_Premium'] = 1;
@@ -528,7 +480,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     $paneNames = array(
       ts('Additional Details') => 'AdditionalDetail',
-      ts('Honoree Information') => 'Honoree'
     );
 
     //Add Premium pane only if Premium is exists.
@@ -574,8 +525,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       );
 
       // see if we need to include this paneName in the current form
-      if ($this->_formType == $type ||
-        CRM_Utils_Array::value("hidden_{$type}", $_POST) ||
+      if ($this->_formType == $type || !empty($_POST["hidden_{$type}"]) ||
         CRM_Utils_Array::value("hidden_{$type}", $defaults)
       ) {
         $showAdditionalInfo = TRUE;
@@ -593,7 +543,8 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
         CRM_Core_Payment_Form::buildDirectDebit($this, TRUE);
       }
       else {
-        eval('CRM_Contribute_Form_AdditionalInfo::build' . $type . '( $this );');
+        $additionalInfoFormFunction = 'build' . $type;
+        CRM_Contribute_Form_AdditionalInfo::$additionalInfoFormFunction($this);
       }
     }
     if (empty($this->_recurPaymentProcessors)) {
@@ -655,7 +606,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       $paymentInstrument = $this->add('select', 'payment_instrument_id',
         ts('Paid By'),
         array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(),
-        FALSE, array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")
+        TRUE, array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")
       );
     }
 
@@ -680,17 +631,17 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
     }
     elseif ((!$this->_ppID && $this->_id) || !$this->_id) {
-      foreach(array(
-                'Overdue',
-                'In Progress'
-              ) as $suppress) {
+      foreach (array(
+                 'Overdue',
+                 'In Progress'
+               ) as $suppress) {
         unset($status[CRM_Utils_Array::key($suppress, $statusName)]);
       }
     }
     if ($this->_id) {
       $contributionStatus = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->_id, 'contribution_status_id');
       $name = CRM_Utils_Array::value($contributionStatus, $statusName);
-      switch($name) {
+      switch ($name) {
         case 'Completed':
         case 'Cancelled':
         case 'Refunded':
@@ -701,17 +652,18 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
           unset($status[CRM_Utils_Array::key('Refunded', $statusName)]);
           break;
         case 'Failed':
-          foreach(array(
-                    'Pending',
-                    'Refunded',
-                    'Completed',
-                    'Cancelled'
-                  ) as $suppress) {
+          foreach (array(
+                     'Pending',
+                     'Refunded',
+                     'Completed',
+                     'Cancelled'
+                   ) as $suppress) {
             unset($status[CRM_Utils_Array::key($suppress, $statusName)]);
           }
           break;
       }
-    } else {
+    }
+    else {
       unset($status[CRM_Utils_Array::key('Refunded', $statusName)]);
     }
 
@@ -752,7 +704,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     $totalAmount = NULL;
     if (empty($this->_lineItems)) {
       $buildPriceSet = FALSE;
-      $priceSets = CRM_Price_BAO_Set::getAssoc(FALSE, 'CiviContribute');
+      $priceSets = CRM_Price_BAO_PriceSet::getAssoc(FALSE, 'CiviContribute');
       if (!empty($priceSets) && !$this->_ppID) {
         $buildPriceSet = TRUE;
       }
@@ -793,23 +745,23 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       $this->assign('hasPriceSets', $hasPriceSets);
       $currencyFreeze = FALSE;
       if (!($this->_action & CRM_Core_Action::UPDATE)) {
-      if ($this->_online || $this->_ppID) {
-        $attributes['total_amount'] = array_merge($attributes['total_amount'], array(
-          'READONLY' => TRUE,
-          'style' => "background-color:#EBECE4"
-        ));
-        $optionTypes = array(
-          '1' => ts('Adjust Pledge Payment Schedule?'),
-          '2' => ts('Adjust Total Pledge Amount?'),
-        );
-        $this->addRadio('option_type',
-          NULL,
-          $optionTypes,
-          array(), '<br/>'
-        );
+        if ($this->_online || $this->_ppID) {
+          $attributes['total_amount'] = array_merge($attributes['total_amount'], array(
+            'READONLY' => TRUE,
+            'style' => "background-color:#EBECE4"
+          ));
+          $optionTypes = array(
+            '1' => ts('Adjust Pledge Payment Schedule?'),
+            '2' => ts('Adjust Total Pledge Amount?'),
+          );
+          $this->addRadio('option_type',
+            NULL,
+            $optionTypes,
+            array(), '<br/>'
+          );
 
-        $currencyFreeze = TRUE;
-      }
+          $currencyFreeze = TRUE;
+        }
       }
 
       $totalAmount = $this->addMoney('total_amount',
@@ -825,41 +777,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     //CRM-7362 --add campaigns.
     CRM_Campaign_BAO_Campaign::addCampaign($this, CRM_Utils_Array::value('campaign_id', $this->_values));
 
-    // CRM-7368 allow user to set or edit PCP link for contributions
-    $siteHasPCPs = CRM_Contribute_PseudoConstant::pcPage();
-    if (!CRM_Utils_Array::crmIsEmptyArray($siteHasPCPs)) {
-      $this->assign('siteHasPCPs', 1);
-      $pcpDataUrl = CRM_Utils_System::url('civicrm/ajax/rest',
-        'className=CRM_Contact_Page_AJAX&fnName=getPCPList&json=1&context=contact&reset=1',
-        FALSE, NULL, FALSE
-      );
-      $this->assign('pcpDataUrl', $pcpDataUrl);
-      $this->addElement('text', 'pcp_made_through', ts('Credit to a Personal Campaign Page'));
-      $this->addElement('hidden', 'pcp_made_through_id', '', array('id' => 'pcp_made_through_id'));
-      $this->addElement('checkbox', 'pcp_display_in_roll', ts('Display in Honor Roll?'), NULL);
-      $this->addElement('text', 'pcp_roll_nickname', ts('Name (for Honor Roll)'));
-      $this->addElement('textarea', 'pcp_personal_note', ts('Personal Note (for Honor Roll)'));
-    }
-
-    // If we have a contact for this contribution, pass cid= to the dataUrl to exclude current contact from autocomplete results
-    if ($this->_contactID) {
-      $dataUrl = CRM_Utils_System::url('civicrm/ajax/rest',
-        "className=CRM_Contact_Page_AJAX&fnName=getContactList&json=1&reset=1&context=softcredit&cid={$this->_contactID}",
-        FALSE, NULL, FALSE
-      );
-    } else {
-      $dataUrl = CRM_Utils_System::url('civicrm/ajax/rest',
-        'className=CRM_Contact_Page_AJAX&fnName=getContactList&json=1&reset=1&context=softcredit',
-        FALSE, NULL, FALSE
-      );
-    }
-    $this->assign('dataUrl', $dataUrl);
-    $this->addElement('text', 'soft_credit_to', ts('Soft Credit To'));
-    // Tell tpl to hide Soft Credit field if contribution is linked directly to a PCP Page
-    if (CRM_Utils_Array::value('pcp_made_through_id', $this->_values)) {
-      $this->assign('pcpLinked', 1);
-    }
-    $this->addElement('hidden', 'soft_contact_id', '', array('id' => 'soft_contact_id'));
+    CRM_Contribute_Form_SoftCredit::buildQuickForm($this);
 
     $js = NULL;
     if (!$this->_mode) {
@@ -929,17 +847,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       $errors['contact[1]'] = ts('Please select a contact or create new contact');
     }
 
-    if (isset($fields['honor_type_id'])) {
-      if (!((CRM_Utils_Array::value('honor_first_name', $fields) &&
-        CRM_Utils_Array::value('honor_last_name', $fields)
-      ) ||
-        CRM_Utils_Array::value('honor_email', $fields)
-      )
-      ) {
-        $errors['honor_first_name'] = ts('Honor First Name and Last Name OR an email should be set.');
-      }
-    }
-
     //check for Credit Card Contribution.
     if ($self->_mode) {
       if (empty($fields['payment_processor_id'])) {
@@ -948,23 +855,15 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     }
 
     // do the amount validations.
-    if (!CRM_Utils_Array::value('total_amount', $fields) && empty($self->_lineItems)) {
+    if (empty($fields['total_amount']) && empty($self->_lineItems)) {
       if ($priceSetId = CRM_Utils_Array::value('price_set_id', $fields)) {
-        CRM_Price_BAO_Field::priceSetValidation($priceSetId, $fields, $errors);
+        CRM_Price_BAO_PriceField::priceSetValidation($priceSetId, $fields, $errors);
       }
     }
 
-    // if honor roll fields are populated but no PCP is selected
-    if (!CRM_Utils_Array::value('pcp_made_through_id', $fields)) {
-      if (CRM_Utils_Array::value('pcp_display_in_roll', $fields) ||
-        CRM_Utils_Array::value('pcp_roll_nickname', $fields) ||
-        CRM_Utils_Array::value('pcp_personal_note', $fields)
-      ) {
-        $errors['pcp_made_through'] = ts('Please select a Personal Campaign Page, OR uncheck Display in Honor Roll and clear both the Honor Roll Name and the Personal Note field.');
-      }
-    }
+    $softErrors = CRM_Contribute_Form_SoftCredit::formRule($fields, $errors, $self);
 
-    if (CRM_Utils_Array::value('total_amount', $fields) && (CRM_Utils_Array::value('net_amount', $fields) || CRM_Utils_Array::value('fee_amount', $fields))){
+    if (!empty($fields['total_amount']) && (!empty($fields['net_amount']) || !empty($fields['fee_amount']))) {
       $sum = CRM_Utils_Rule::cleanMoney($fields['net_amount']) + CRM_Utils_Rule::cleanMoney($fields['fee_amount']);
       if (CRM_Utils_Rule::cleanMoney($fields['total_amount']) != $sum) {
         $errors['total_amount'] = ts('The sum of fee amount and net amount must be equal to total amount');
@@ -976,10 +875,25 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     }
 
     //FIXME FOR NEW DATA FLOW http://wiki.civicrm.org/confluence/display/CRM/CiviAccounts+4.3+Data+Flow
-     if (CRM_Utils_Array::value('fee_amount', $fields) 
-      && $financialType = CRM_Contribute_BAO_Contribution::validateFinancialType($fields['financial_type_id'])) {
-      $errors['financial_type_id'] = ts("Financial Account of account relationship of 'Expense Account is' is not configured for Financial Type : ") . $financialType;  
+     if (!empty($fields['fee_amount']) && $financialType = CRM_Contribute_BAO_Contribution::validateFinancialType($fields['financial_type_id'])) {
+      $errors['financial_type_id'] = ts("Financial Account of account relationship of 'Expense Account is' is not configured for Financial Type : ") . $financialType;
+    }
+
+    // $trxn_id must be unique CRM-13919
+    if (!empty($fields['trxn_id'])) {
+      $queryParams = array(1 => array($fields['trxn_id'], 'String'));
+      $query = 'select count(*) from civicrm_contribution where trxn_id = %1';
+      if ($self->_id) {
+        $queryParams[2] = array((int)$self->_id, 'Integer');
+        $query .= ' and id !=%2';
+      }
+      $tCnt = CRM_Core_DAO::singleValueQuery($query, $queryParams);
+      if ($tCnt) {
+        $errors['trxn_id'] = ts('Transaction ID\'s must be unique. Transaction \'%1\' already exists in your database.', array(1 => $fields['trxn_id']));
+      }
     }
+
+    $errors = array_merge($errors, $softErrors);
     return $errors;
   }
 
@@ -1002,11 +916,11 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     // get the submitted form values.
     $submittedValues = $this->controller->exportValues($this->_name);
-    if (CRM_Utils_Array::value('price_set_id', $submittedValues) && $this->_action & CRM_Core_Action::UPDATE ) {
-      $line  = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'contribution');
+    if (!empty($submittedValues['price_set_id']) && $this->_action & CRM_Core_Action::UPDATE) {
+      $line = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'contribution');
       $lineID = key($line);
-      $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_Field', CRM_Utils_Array::value('price_field_id', $line[$lineID]), 'price_set_id');
-      $quickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_Set', $priceSetId, 'is_quick_config');
+      $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', CRM_Utils_Array::value('price_field_id', $line[$lineID]), 'price_set_id');
+      $quickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config');
       if ($quickConfig) {
         CRM_Price_BAO_LineItem::deleteLineItems($this->_id, 'civicrm_contribution');
       }
@@ -1017,8 +931,8 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     $priceSetId = $pId = NULL;
     $priceSetId = CRM_Utils_Array::value('price_set_id', $submittedValues);
     if (empty($priceSetId) && !$this->_id) {
-      $this->_priceSetId = $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_Set', 'default_contribution_amount', 'id', 'name');
-      $this->_priceSet = current(CRM_Price_BAO_Set::getSetDetail($priceSetId));
+      $this->_priceSetId = $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', 'default_contribution_amount', 'id', 'name');
+      $this->_priceSet = current(CRM_Price_BAO_PriceSet::getSetDetail($priceSetId));
       $fieldID = key($this->_priceSet['fields']);
       $fieldValueId = key($this->_priceSet['fields'][$fieldID]['options']);
       $this->_priceSet['fields'][$fieldID]['options'][$fieldValueId]['amount'] = $submittedValues['total_amount'];
@@ -1026,7 +940,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     }
 
     if ($priceSetId) {
-      CRM_Price_BAO_Set::processAmount($this->_priceSet['fields'],
+      CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'],
         $submittedValues, $lineItem[$priceSetId]);
 
       $submittedValues['total_amount'] = CRM_Utils_Array::value('amount', $submittedValues);
@@ -1035,7 +949,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       //CRM-10964
       $pId = ($this->_compId && $this->_context == 'participant') ? $this->_compId : CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $this->_id, 'participant_id', 'contribution_id');
     }
-    if (!$priceSetId && CRM_Utils_Array::value('total_amount', $submittedValues) && $this->_id) {
+    if (!$priceSetId && !empty($submittedValues['total_amount']) && $this->_id) {
       // 10117 update th line items for participants
       if ($pId) {
         $entityTable = 'participant';
@@ -1046,9 +960,10 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
         );
         CRM_Event_BAO_Participant::add($participantParams);
         if (empty($this->_lineItems)) {
-          $this->_lineItems = CRM_Price_BAO_LineItem::getLineItems($entityID, 'participant',1);
+          $this->_lineItems = CRM_Price_BAO_LineItem::getLineItems($entityID, 'participant', 1);
         }
-      } else {
+      }
+      else {
         $entityTable = 'contribution';
         $entityID = $this->_id;
       }
@@ -1059,23 +974,25 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
       $itemId = key($lineItems);
       $fieldType = NULL;
-      if ($itemId && CRM_Utils_Array::value('price_field_id', $lineItems[$itemId])) {
-        $fieldType = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_Field', $lineItems[$itemId]['price_field_id'], 'html_type');
+      if ($itemId && !empty($lineItems[$itemId]['price_field_id'])) {
+        $fieldType = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'html_type');
       }
       $lineItems[$itemId]['unit_price'] = $lineItems[$itemId]['line_total'] = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('total_amount', $submittedValues));
       // 10117 update th line items for participants
-      $this->_priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_Field', $lineItems[$itemId]['price_field_id'], 'price_set_id');
-      $lineItem[$this->_priceSetId] = $lineItems;
+      if (!empty($lineItems[$itemId]['price_field_id'])) {
+        $this->_priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id');
+        $lineItem[$this->_priceSetId] = $lineItems;
+      }
     }
     $isQuickConfig = 0;
-    if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_Set', $this->_priceSetId, 'is_quick_config')) {
+    if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) {
       $isQuickConfig = 1;
     }
     //CRM-11529 for quick config backoffice transactions
     //when financial_type_id is passed in form, update the
     //lineitems with the financial type selected in form
-    if ($isQuickConfig && CRM_Utils_Array::value('financial_type_id', $submittedValues)
-      && CRM_Utils_Array::value($this->_priceSetId, $lineItem)) {
+    if ($isQuickConfig && !empty($submittedValues['financial_type_id']) && CRM_Utils_Array::value($this->_priceSetId, $lineItem)
+    ) {
       foreach ($lineItem[$this->_priceSetId] as &$values) {
         $values['financial_type_id'] = $submittedValues['financial_type_id'];
       }
@@ -1086,12 +1003,37 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     }
     $this->assign('lineItem', !empty($lineItem) && !$isQuickConfig ? $lineItem : FALSE);
 
-    if (CRM_Utils_Array::value('soft_credit_to', $submittedValues)) {
-      $submittedValues['soft_credit_to'] = $submittedValues['soft_contact_id'];
+    if (!empty($submittedValues['pcp_made_through_id'])) {
+      $pcp = array();
+      $fields = array(
+        'pcp_made_through_id',
+        'pcp_display_in_roll',
+        'pcp_roll_nickname',
+        'pcp_personal_note',
+      );
+      foreach ($fields as $f) {
+        $pcp[$f] = CRM_Utils_Array::value($f, $submittedValues);
+      }
+    }
+    else {
+      //build soft credit params
+      if (!empty($submittedValues['soft_credit_contact_select_id'])) {
+        $softParams = $softIDs =array();
+        foreach ($submittedValues['soft_credit_contact_select_id'] as $key => $val) {
+          if ($val && $submittedValues['soft_credit_amount'][$key]) {
+            $softParams[$key]['contact_id'] = $val;
+            $softParams[$key]['amount'] = CRM_Utils_Rule::cleanMoney($submittedValues['soft_credit_amount'][$key]);
+            $softParams[$key]['soft_credit_type_id'] = $submittedValues['soft_credit_type'][$key];
+            if (!empty($submittedValues['soft_credit_id'][$key])) {
+              $softIDs[] = $softParams[$key]['id'] = $submittedValues['soft_credit_id'][$key];
+            }
+          }
+        }
+      }
     }
 
     // set the contact, when contact is selected
-    if (CRM_Utils_Array::value('contact_select_id', $submittedValues)) {
+    if (!empty($submittedValues['contact_select_id'])) {
       $this->_contactID = $submittedValues['contact_select_id'][1];
     }
 
@@ -1120,19 +1062,19 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
         'cancel_reason',
         'source',
         'check_number',
-        'soft_credit_to',
-        'pcp_made_through_id',
-        'pcp_display_in_roll',
-        'pcp_roll_nickname',
-        'pcp_personal_note',
       );
       foreach ($fields as $f) {
         $params[$f] = CRM_Utils_Array::value($f, $formValues);
       }
 
-      if ($softID = CRM_Utils_Array::value('softID', $this->_values)) {
-        $params['softID'] = $softID;
+      if (!empty($pcp)) {
+        $params['pcp'] = $pcp;
       }
+      if (!empty($softParams)) {
+        $params['soft_credit'] = $softParams;
+        $params['soft_credit_ids'] = $softIDs;
+      }
+
       //if priceset is used, no need to cleanup money
       //CRM-5740
       if ($priceSetId) {
@@ -1149,14 +1091,15 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
         $params[$d] = CRM_Utils_Date::processDate($formValues[$d], $formValues[$d . '_time'], TRUE);
       }
 
-      if (CRM_Utils_Array::value('is_email_receipt', $formValues)) {
+      if (!empty($formValues['is_email_receipt'])) {
         $params['receipt_date'] = date("Y-m-d");
       }
 
       if ($params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Cancelled', 'name')
-          || $params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Refunded', 'name')) {
+        || $params['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Refunded', 'name')
+      ) {
         if (CRM_Utils_System::isNull(CRM_Utils_Array::value('cancel_date', $params))) {
-          $params['cancel_date'] = date("Y-m-d");
+          $params['cancel_date'] = date('Y-m-d');
         }
       }
       else {
@@ -1203,8 +1146,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
             $selectProduct = $formValues['product_name'][0];
           }
           // if there is a product - compare the value to the contribution amount
-          if (isset($selectProduct))
-           {
+          if (isset($selectProduct)) {
             $productDAO = new CRM_Contribute_DAO_Product();
             $productDAO->id = $selectProduct;
             $productDAO->find(TRUE);
@@ -1254,7 +1196,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
 
       //send receipt mail.
-      if ($contribution->id && CRM_Utils_Array::value('is_email_receipt', $formValues)) {
+      if ($contribution->id && !empty($formValues['is_email_receipt'])) {
         $formValues['contact_id'] = $this->_contactID;
         $formValues['contribution_id'] = $contribution->id;
 
@@ -1319,7 +1261,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
 
       $statusMsg = ts('The contribution record has been saved.');
-      if (CRM_Utils_Array::value('is_email_receipt', $formValues) && $sendReceipt) {
+      if (!empty($formValues['is_email_receipt']) && $sendReceipt) {
         $statusMsg .= ' ' . ts('A receipt has been emailed to the contributor.');
       }
 
@@ -1368,12 +1310,12 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
         unset($submittedValues[$key]);
       }
     }
-     
+
     // CRM-12680 set $_lineItem if its not set
     if (empty($this->_lineItem) && !empty($lineItem)) {
       $this->_lineItem = $lineItem;
     }
-    
+
     //Get the rquire fields value only.
     $params = $this->_params = $submittedValues;
 
@@ -1382,14 +1324,14 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     );
 
     //get the payment processor id as per mode.
-    $this->_params['payment_processor'] = $params['payment_processor_id'] = 
+    $this->_params['payment_processor'] = $params['payment_processor_id'] =
       $this->_params['payment_processor_id'] = $submittedValues['payment_processor_id'] = $this->_paymentProcessor['id'];
 
     $now = date('YmdHis');
     $fields = array();
 
     // we need to retrieve email address
-    if ($this->_context == 'standalone' && CRM_Utils_Array::value('is_email_receipt', $submittedValues)) {
+    if ($this->_context == 'standalone' && !empty($submittedValues['is_email_receipt'])) {
       list($this->userDisplayName,
         $this->userEmail
         ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID);
@@ -1424,7 +1366,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
     }
 
-    if (CRM_Utils_Array::value('source', $params)) {
+    if (!empty($params['source'])) {
       unset($params['source']);
     }
     $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields,
@@ -1449,11 +1391,11 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       $config->defaultCurrency
     );
     $this->_params['payment_action'] = 'Sale';
-    if (CRM_Utils_Array::value('receive_date', $this->_params)) {
+    if (!empty($this->_params['receive_date'])) {
       $this->_params['receive_date'] = CRM_Utils_Date::processDate($this->_params['receive_date'], $this->_params['receive_date_time']);
     }
 
-    if (CRM_Utils_Array::value('soft_credit_to', $params)) {
+    if (!empty($params['soft_credit_to'])) {
       $this->_params['soft_credit_to'] = $params['soft_credit_to'];
       $this->_params['pcp_made_through_id'] = $params['pcp_made_through_id'];
     }
@@ -1489,7 +1431,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     // if folks need to use it
     $paymentParams['contributionType_name'] = $this->_params['contributionType_name'] = $contributionType->name;
     $paymentParams['contributionPageID'] = NULL;
-    if (CRM_Utils_Array::value('is_email_receipt', $this->_params)) {
+    if (!empty($this->_params['is_email_receipt'])) {
       $paymentParams['email'] = $this->userEmail;
       $paymentParams['is_email_receipt'] = 1;
     }
@@ -1497,10 +1439,10 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       $paymentParams['is_email_receipt'] = 0;
       $this->_params['is_email_receipt'] = 0;
     }
-    if (CRM_Utils_Array::value('receive_date', $this->_params)) {
+    if (!empty($this->_params['receive_date'])) {
       $paymentParams['receive_date'] = $this->_params['receive_date'];
     }
-    if (CRM_Utils_Array::value('receive_date', $this->_params)) {
+    if (!empty($this->_params['receive_date'])) {
       $paymentParams['receive_date'] = $this->_params['receive_date'];
     }
 
@@ -1509,7 +1451,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     // For recurring contribution, create Contribution Record first.
     // Contribution ID, Recurring ID and Contact ID needed
     // When we get a callback from the payment processor, CRM-7115
-    if (CRM_Utils_Array::value('is_recur', $paymentParams)) {
+    if (!empty($paymentParams['is_recur'])) {
       $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($this,
         $this->_params,
         $result,
@@ -1533,11 +1475,11 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     if (is_a($result, 'CRM_Core_Error')) {
       //make sure to cleanup db for recurring case.
-      if (CRM_Utils_Array::value('contributionID', $paymentParams)) {
+      if (!empty($paymentParams['contributionID'])) {
         CRM_Core_Error::debug_log_message(CRM_Core_Error::getMessages($result) . "contact id={$this->_contactID} (deleting contribution {$paymentParams['contributionID']}");
         CRM_Contribute_BAO_Contribution::deleteContribution($paymentParams['contributionID']);
       }
-      if (CRM_Utils_Array::value('contributionRecurID', $paymentParams)) {
+      if (!empty($paymentParams['contributionRecurID'])) {
         CRM_Core_Error::debug_log_message(CRM_Core_Error::getMessages($result) . "contact id={$this->_contactID} (deleting recurring contribution {$paymentParams['contributionRecurID']}");
         CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']);
       }
@@ -1560,7 +1502,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     $this->_params['receive_date'] = $now;
 
-    if (CRM_Utils_Array::value('is_email_receipt', $this->_params)) {
+    if (!empty($this->_params['is_email_receipt'])) {
       $this->_params['receipt_date'] = $now;
     }
     else {
@@ -1603,7 +1545,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     );
 
 
-    if (!CRM_Utils_Array::value('is_recur', $paymentParams)) {
+    if (empty($paymentParams['is_recur'])) {
       $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($this,
         $this->_params,
         $result,
@@ -1614,9 +1556,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     }
 
     //send receipt mail.
-    if ($contribution->id &&
-      CRM_Utils_Array::value('is_email_receipt', $this->_params)
-    ) {
+    if ($contribution->id && !empty($this->_params['is_email_receipt'])) {
       $this->_params['trxn_id'] = CRM_Utils_Array::value('trxn_id', $result);
       $this->_params['contact_id'] = $this->_contactID;
       $this->_params['contribution_id'] = $contribution->id;
@@ -1647,7 +1587,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     if ($contribution->id) {
       $statusMsg = ts('The contribution record has been processed.');
-      if (CRM_Utils_Array::value('is_email_receipt', $this->_params) && $sendReceipt) {
+      if (!empty($this->_params['is_email_receipt']) && $sendReceipt) {
         $statusMsg .= ' ' . ts('A receipt has been emailed to the contributor.');
       }
       CRM_Core_Session::setStatus($statusMsg, ts('Complete'), 'success');