Merge pull request #10340 from Stoob/master
[civicrm-core.git] / CRM / Contribute / Form / Contribution / Main.php
index 9b9f4ad476098ace633778eb43e73e74d84a4d91..2187147acd2be48e54d3a3e4a9ac201d1c6e8c6e 100644 (file)
@@ -3,7 +3,7 @@
   +--------------------------------------------------------------------+
   | CiviCRM version 4.7                                                |
   +--------------------------------------------------------------------+
-  | Copyright CiviCRM LLC (c) 2004-2016                                |
+  | Copyright CiviCRM LLC (c) 2004-2017                                |
   +--------------------------------------------------------------------+
   | This file is a part of CiviCRM.                                    |
   |                                                                    |
@@ -28,7 +28,7 @@
 /**
  *
  * @package CRM
- * @copyright CiviCRM LLC (c) 2004-2016
+ * @copyright CiviCRM LLC (c) 2004-2017
  */
 
 /**
@@ -65,12 +65,41 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $this->_paymentProcessors = $this->get('paymentProcessors');
     $this->preProcessPaymentOptions();
 
+    if (!empty($this->_ccid)) {
+      $payment = CRM_Contribute_BAO_Contribution::getPaymentInfo($this->_ccid, 'contribution');
+      //bounce if the contribution is not pending.
+      if (empty($payment['balance'])) {
+        CRM_Core_Error::statusBounce(ts("Returning since contribution has already been handled."));
+      }
+      if (!empty($payment['total'])) {
+        $this->_pendingAmount = $payment['total'];
+        $this->assign('pendingAmount', $this->_pendingAmount);
+      }
+      $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($this->_ccid);
+      foreach (array_keys($lineItems) as $id) {
+        $lineItems[$id]['id'] = $id;
+      }
+      $itemId = key($lineItems);
+      if ($itemId && !empty($lineItems[$itemId]['price_field_id'])) {
+        $this->_priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id');
+      }
+
+      if (!empty($lineItems[$itemId]['price_field_id'])) {
+        $this->_lineItem[$this->_priceSetId] = $lineItems;
+      }
+      $isQuickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config');
+      $this->assign('lineItem', $this->_lineItem);
+      $this->assign('is_quick_config', $isQuickConfig);
+      $this->assign('priceSetID', $this->_priceSetId);
+    }
+
     // Make the contributionPageID available to the template
     $this->assign('contributionPageID', $this->_id);
+    $this->assign('ccid', $this->_ccid);
     $this->assign('isShare', CRM_Utils_Array::value('is_share', $this->_values));
     $this->assign('isConfirmEnabled', CRM_Utils_Array::value('is_confirm_enabled', $this->_values));
 
-    $this->assign('reset', CRM_Utils_Request::retrieve('reset', 'Boolean', CRM_Core_DAO::$_nullObject));
+    $this->assign('reset', CRM_Utils_Request::retrieve('reset', 'Boolean'));
     $this->assign('mainDisplay', CRM_Utils_Request::retrieve('_qf_Main_display', 'Boolean',
       CRM_Core_DAO::$_nullObject));
 
@@ -127,6 +156,9 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $billingDefaults = $this->getProfileDefaults('Billing', $contactID);
       $this->_defaults = array_merge($this->_defaults, $billingDefaults);
     }
+    if (!empty($this->_ccid) && !empty($this->_pendingAmount)) {
+      $this->_defaults['total_amount'] = CRM_Utils_Money::format($this->_pendingAmount, NULL, '%a');
+    }
 
     /*
      * hack to simplify credit card entry for testing
@@ -286,13 +318,15 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
   public function buildQuickForm() {
     // build profiles first so that we can determine address fields etc
     // and then show copy address checkbox
-    $this->buildCustom($this->_values['custom_pre_id'], 'customPre');
-    $this->buildCustom($this->_values['custom_post_id'], 'customPost');
+    if (empty($this->_ccid)) {
+      $this->buildCustom($this->_values['custom_pre_id'], 'customPre');
+      $this->buildCustom($this->_values['custom_post_id'], 'customPost');
 
-    // CRM-18399: used by template to pass pre profile id as a url arg
-    $this->assign('custom_pre_id', $this->_values['custom_pre_id']);
+      // CRM-18399: used by template to pass pre profile id as a url arg
+      $this->assign('custom_pre_id', $this->_values['custom_pre_id']);
 
-    $this->buildComponentForm($this->_id, $this);
+      $this->buildComponentForm($this->_id, $this);
+    }
 
     // Build payment processor form
     CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
@@ -306,12 +340,20 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     }
 
     $this->applyFilter('__ALL__', 'trim');
-    $this->add('text', "email-{$this->_bltID}",
-      ts('Email Address'),
-      array('size' => 30, 'maxlength' => 60, 'class' => 'email'),
-      TRUE
-    );
-    $this->addRule("email-{$this->_bltID}", ts('Email is not valid.'), 'email');
+    if (empty($this->_ccid)) {
+      if ($this->_emailExists == FALSE) {
+        $this->add('text', "email-{$this->_bltID}",
+          ts('Email Address'),
+          array('size' => 30, 'maxlength' => 60, 'class' => 'email'),
+          TRUE
+        );
+        $this->addRule("email-{$this->_bltID}", ts('Email is not valid.'), 'email');
+      }
+    }
+    else {
+      $this->addElement('hidden', "email-{$this->_bltID}", 1);
+      $this->add('text', 'total_amount', ts('Total Amount'), array('readonly' => TRUE), FALSE);
+    }
     $pps = array();
     //@todo - this should be replaced by a check as to whether billing fields are set
     $onlinePaymentProcessorEnabled = FALSE;
@@ -350,7 +392,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     //build pledge block.
     $this->_useForMember = 0;
     //don't build membership block when pledge_id is passed
-    if (empty($this->_values['pledge_id'])) {
+    if (empty($this->_values['pledge_id']) && empty($this->_ccid)) {
       $this->_separateMembershipPayment = FALSE;
       if (in_array('CiviMember', $config->enableComponents)) {
         $isTest = 0;
@@ -381,7 +423,9 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $this->add('hidden', 'priceSetId', $this->_priceSetId);
       // build price set form.
       $this->set('priceSetId', $this->_priceSetId);
-      CRM_Price_BAO_PriceSet::buildPriceSet($this);
+      if (empty($this->_ccid)) {
+        CRM_Price_BAO_PriceSet::buildPriceSet($this);
+      }
       if ($this->_values['is_monetary'] &&
         $this->_values['is_recur'] && empty($this->_values['pledge_id'])
       ) {
@@ -389,7 +433,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       }
     }
 
-    if ($this->_priceSetId) {
+    if ($this->_priceSetId && empty($this->_ccid)) {
       $is_quick_config = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config');
       if ($is_quick_config) {
         $this->_useForMember = 0;
@@ -398,12 +442,12 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     }
 
     //we allow premium for pledge during pledge creation only.
-    if (empty($this->_values['pledge_id'])) {
+    if (empty($this->_values['pledge_id']) && empty($this->_ccid)) {
       CRM_Contribute_BAO_Premium::buildPremiumBlock($this, $this->_id, TRUE);
     }
 
     //don't build pledge block when mid is passed
-    if (!$this->_mid) {
+    if (!$this->_mid && empty($this->_ccid)) {
       $config = CRM_Core_Config::singleton();
       if (in_array('CiviPledge', $config->enableComponents) && !empty($this->_values['pledge_block_id'])) {
         CRM_Pledge_BAO_PledgeBlock::buildPledgeBlock($this);
@@ -411,7 +455,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     }
 
     //to create an cms user
-    if (!$this->_contactID) {
+    if (!$this->_contactID && empty($this->_ccid)) {
       $createCMSUser = FALSE;
 
       if ($this->_values['custom_pre_id']) {
@@ -441,7 +485,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         CRM_Core_BAO_CMSUser::buildForm($this, $profileID, TRUE);
       }
     }
-    if ($this->_pcpId) {
+    if ($this->_pcpId && empty($this->_ccid)) {
       if ($pcpSupporter = CRM_PCP_BAO_PCP::displayName($this->_pcpId)) {
         $pcp_supporter_text = ts('This contribution is being made thanks to the effort of <strong>%1</strong>, who supports our campaign.', array(1 => $pcpSupporter));
         // Only tell people that can also create a PCP if the contribution page has a non-empty value in the "Create Personal Campaign Page link" field.
@@ -468,7 +512,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         $this->add('textarea', 'pcp_personal_note', ts('Personal Note'), array('style' => 'height: 3em; width: 40em;'));
       }
     }
-    if (empty($this->_values['fee'])) {
+    if (empty($this->_values['fee']) && empty($this->_ccid)) {
       CRM_Core_Error::fatal(ts('This page does not have any price fields configured or you may not have permission for them. Please contact the site administrator for more details.'));
     }
 
@@ -502,6 +546,10 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       if (empty($this->_values['is_confirm_enabled'])) {
         $submitButton['js'] = array('onclick' => "return submitOnce(this,'" . $this->_name . "','" . ts('Processing') . "');");
       }
+      //change button name for updating contribution
+      if (!empty($this->_ccid)) {
+        $submitButton['name'] = ts('Confirm Payment');
+      }
       $this->addButtons(array($submitButton));
     }
 
@@ -520,6 +568,13 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
 
     $form->assign('is_recur_interval', CRM_Utils_Array::value('is_recur_interval', $form->_values));
     $form->assign('is_recur_installments', CRM_Utils_Array::value('is_recur_installments', $form->_values));
+    $paymentObject = $form->getVar('_paymentObject');
+    if ($paymentObject) {
+      $form->assign('recurringHelpText', $paymentObject->getText('contributionPageRecurringHelp', array(
+        'is_recur_installments' => !empty($form->_values['is_recur_installments']),
+        'is_email_receipt' => !empty($form->_values['is_email_receipt']),
+      )));
+    }
 
     $form->add('checkbox', 'is_recur', ts('I want to contribute this amount'), NULL);
 
@@ -620,7 +675,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     }
 
     //check for atleast one pricefields should be selected
-    if (!empty($fields['priceSetId'])) {
+    if (!empty($fields['priceSetId']) && empty($self->_ccid)) {
       $priceField = new CRM_Price_DAO_PriceField();
       $priceField->price_set_id = $fields['priceSetId'];
       $priceField->orderBy('weight');
@@ -674,11 +729,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         // For anonymous user check using dedupe rule
         // if user has Cancelled Membership
         if (!$memContactID) {
-          $dedupeParams = CRM_Dedupe_Finder::formatParams($fields, 'Individual');
-          $dedupeParams['check_permission'] = FALSE;
-          $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual');
-          // if we find more than one contact, use the first one
-          $memContactID = CRM_Utils_Array::value(0, $ids);
+          $memContactID = CRM_Contact_BAO_Contact::getFirstDuplicateContact($fields, 'Individual', 'Unsupervised', array(), FALSE);
         }
         $currentMemberships = CRM_Member_BAO_Membership::getContactsCancelledMembership($memContactID,
           $is_test
@@ -737,7 +788,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
           $errors["price_{$errorKey}"] = ts('Additional Contribution is required.');
         }
       }
-      if (empty($check)) {
+      if (empty($check) && empty($self->_ccid)) {
         if ($self->_useForMember == 1 && $membershipIsActive) {
           $errors['_qf_default'] = ts('Select at least one option from Membership Type(s).');
         }
@@ -815,9 +866,16 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         $fields, $lineItem
       );
 
+      $minAmt = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $fields['priceSetId'], 'min_amount');
       if ($fields['amount'] < 0) {
         $errors['_qf_default'] = ts('Contribution can not be less than zero. Please select the options accordingly');
       }
+      elseif (!empty($minAmt) && $fields['amount'] < $minAmt) {
+        $errors['_qf_default'] = ts('A minimum amount of %1 should be selected from Contribution(s).', array(
+          1 => CRM_Utils_Money::format($minAmt),
+        ));
+      }
+
       $amount = $fields['amount'];
     }
 
@@ -1008,7 +1066,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
 
     $params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency;
 
-    $is_quick_config = 0;
+    // @todo refactor this & leverage it from the unit tests.
     if (!empty($params['priceSetId'])) {
       $is_quick_config = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config');
       if ($is_quick_config) {
@@ -1048,8 +1106,14 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         }
       }
     }
-    // from here on down, $params['amount'] holds a monetary value (or null) rather than an option ID
-    $params['amount'] = self::computeAmount($params, $this->_values);
+
+    if (!empty($this->_ccid) && !empty($this->_pendingAmount)) {
+      $params['amount'] = $this->_pendingAmount;
+    }
+    else {
+      // from here on down, $params['amount'] holds a monetary value (or null) rather than an option ID
+      $params['amount'] = self::computeAmount($params, $this->_values);
+    }
 
     $params['separate_amount'] = $params['amount'];
     $memFee = NULL;
@@ -1066,7 +1130,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       }
     }
     //If the membership & contribution is used in contribution page & not separate payment
-    $fieldId = $memPresent = $membershipLabel = $fieldOption = $is_quick_config = NULL;
+    $memPresent = $membershipLabel = $fieldOption = $is_quick_config = NULL;
     $proceFieldAmount = 0;
     if (property_exists($this, '_separateMembershipPayment') && $this->_separateMembershipPayment == 0) {
       $is_quick_config = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config');
@@ -1099,7 +1163,10 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $this->set('amount_level', CRM_Utils_Array::value('amount_level', $params));
     }
 
-    if ($priceSetId = CRM_Utils_Array::value('priceSetId', $params)) {
+    if (!empty($this->_ccid)) {
+      $this->set('lineItem', $this->_lineItem);
+    }
+    elseif ($priceSetId = CRM_Utils_Array::value('priceSetId', $params)) {
       $lineItem = array();
       $is_quick_config = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config');
       if ($is_quick_config) {
@@ -1160,7 +1227,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $this->assign('is_pay_later', $params['is_pay_later']);
     if ($params['is_pay_later']) {
       $this->assign('pay_later_text', $this->_values['pay_later_text']);
-      $this->assign('pay_later_receipt', $this->_values['pay_later_receipt']);
+      $this->assign('pay_later_receipt', CRM_Utils_Array::value('pay_later_receipt', $this->_values));
     }
 
     if ($this->_membershipBlock['is_separate_payment'] && !empty($params['separate_amount'])) {