CRM-16867 add function to determin combination of membership types in a priceset
[civicrm-core.git] / CRM / Contribute / Form / ContributionBase.php
index ba850bd534e4ad76f0d5f7986a956c9974da5924..bd69387ea1381713a55faa74ea42e154bcabae2b 100644 (file)
@@ -73,6 +73,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
    * @var array
    */
   public $_paymentProcessor;
+
   public $_paymentObject = NULL;
 
   /**
@@ -99,7 +100,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
    *
    * @var array
    */
-  public $_params;
+  public $_params = array();
 
   /**
    * The fields involved in this contribution page
@@ -203,7 +204,6 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
    * @throws \Exception
    */
   public function preProcess() {
-    $session = CRM_Core_Session::singleton();
 
     // current contribution page id
     $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this);
@@ -214,7 +214,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
     }
 
     // this was used prior to the cleverer this_>getContactID - unsure now
-    $this->_userID = $session->get('userID');
+    $this->_userID = CRM_Core_Session::singleton()->get('userID');
 
     //Check if honor block is enabled for current contribution
     $ufJoinParams = array(
@@ -309,41 +309,15 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
       $isMonetary = CRM_Utils_Array::value('is_monetary', $this->_values);
       $isPayLater = CRM_Utils_Array::value('is_pay_later', $this->_values);
 
-      //FIXME: to support multiple payment processors
       if ($isMonetary &&
         (!$isPayLater || !empty($this->_values['payment_processor']))
       ) {
-        $ppID = CRM_Utils_Array::value('payment_processor', $this->_values);
-        if (!$ppID) {
-          CRM_Core_Error::fatal(ts('A payment processor must be selected for this contribution page (contact the site administrator for assistance).'));
-        }
-
-        $paymentProcessorIDs = explode(CRM_Core_DAO::VALUE_SEPARATOR, $ppID);
-
-        $this->_paymentProcessors = CRM_Financial_BAO_PaymentProcessor::getPayments($paymentProcessorIDs, $this->_mode);
-
-        $this->set('paymentProcessors', $this->_paymentProcessors);
-
-        if (!empty($this->_paymentProcessors)) {
-          foreach ($this->_paymentProcessors as $paymentProcessorID => $paymentProcessorDetail) {
-            if (($processor = Civi\Payment\System::singleton()->getByProcessor($paymentProcessorDetail)) != FALSE) {
-              // We don't really know why we do this.
-              $this->_paymentObject = $processor;
-            }
+        $this->_paymentProcessorIDs = explode(
+          CRM_Core_DAO::VALUE_SEPARATOR,
+          CRM_Utils_Array::value('payment_processor', $this->_values)
+        );
 
-            if (empty($this->_paymentProcessor) && $paymentProcessorDetail['is_default'] == 1 || (count($this->_paymentProcessors) == 1)
-            ) {
-              $this->_paymentProcessor = $paymentProcessorDetail;
-              $this->assign('paymentProcessor', $this->_paymentProcessor);
-            }
-          }
-          if (empty($this->_paymentObject)) {
-            throw new CRM_Core_Exception(ts('No valid payment processor'));
-          }
-        }
-        else {
-          throw new CRM_Core_Exception(ts('A payment processor configured for this page might be disabled (contact the site administrator for assistance).'));
-        }
+        $this->assignPaymentProcessor();
       }
 
       // get price info
@@ -866,4 +840,200 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
     }
   }
 
+  /**
+   * Build Membership  Block in Contribution Pages.
+   *
+   * @param int $cid
+   *   Contact checked for having a current membership for a particular membership.
+   * @param bool $isContributionMainPage
+   *   Is this the main page? If so add form input fields.
+   *   (or better yet don't have this functionality in a function shared with forms that don't share it).
+   * @param int $selectedMembershipTypeID
+   *   Selected membership id.
+   * @param bool $thankPage
+   *   Thank you page.
+   * @param null $isTest
+   *
+   * @return bool
+   *   Is this a separate membership payment
+   */
+  protected function buildMembershipBlock(
+    $cid,
+    $isContributionMainPage = FALSE,
+    $selectedMembershipTypeID = NULL,
+    $thankPage = FALSE,
+    $isTest = NULL
+  ) {
+
+    $separateMembershipPayment = FALSE;
+    if ($this->_membershipBlock) {
+      $this->_currentMemberships = array();
+
+      $membershipTypeIds = $membershipTypes = $radio = array();
+      $membershipPriceset = (!empty($this->_priceSetId) && $this->_useForMember) ? TRUE : FALSE;
+
+      $allowAutoRenewMembership = $autoRenewOption = FALSE;
+      $autoRenewMembershipTypeOptions = array();
+
+      $separateMembershipPayment = CRM_Utils_Array::value('is_separate_payment', $this->_membershipBlock);
+
+      if ($membershipPriceset) {
+        foreach ($this->_priceSet['fields'] as $pField) {
+          if (empty($pField['options'])) {
+            continue;
+          }
+          foreach ($pField['options'] as $opId => $opValues) {
+            if (empty($opValues['membership_type_id'])) {
+              continue;
+            }
+            $membershipTypeIds[$opValues['membership_type_id']] = $opValues['membership_type_id'];
+          }
+        }
+      }
+      elseif (!empty($this->_membershipBlock['membership_types'])) {
+        $membershipTypeIds = explode(',', $this->_membershipBlock['membership_types']);
+      }
+
+      if (!empty($membershipTypeIds)) {
+        //set status message if wrong membershipType is included in membershipBlock
+        if (isset($this->_mid) && !$membershipPriceset) {
+          $membershipTypeID = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership',
+            $this->_mid,
+            'membership_type_id'
+          );
+          if (!in_array($membershipTypeID, $membershipTypeIds)) {
+            CRM_Core_Session::setStatus(ts("Oops. The membership you're trying to renew appears to be invalid. Contact your site administrator if you need assistance. If you continue, you will be issued a new membership."), ts('Invalid Membership'), 'error');
+          }
+        }
+
+        $membershipTypeValues = CRM_Member_BAO_Membership::buildMembershipTypeValues($this, $membershipTypeIds);
+        $this->_membershipTypeValues = $membershipTypeValues;
+        $endDate = NULL;
+        foreach ($membershipTypeIds as $value) {
+          $memType = $membershipTypeValues[$value];
+          if ($selectedMembershipTypeID != NULL) {
+            if ($memType['id'] == $selectedMembershipTypeID) {
+              $this->assign('minimum_fee',
+                CRM_Utils_Array::value('minimum_fee', $memType)
+              );
+              $this->assign('membership_name', $memType['name']);
+              if (!$thankPage && $cid) {
+                $membership = new CRM_Member_DAO_Membership();
+                $membership->contact_id = $cid;
+                $membership->membership_type_id = $memType['id'];
+                if ($membership->find(TRUE)) {
+                  $this->assign('renewal_mode', TRUE);
+                  $memType['current_membership'] = $membership->end_date;
+                  $this->_currentMemberships[$membership->membership_type_id] = $membership->membership_type_id;
+                }
+              }
+              $membershipTypes[] = $memType;
+            }
+          }
+          elseif ($memType['is_active']) {
+            $javascriptMethod = NULL;
+            $allowAutoRenewOpt = 1;
+            if (is_array($this->_paymentProcessors)) {
+              foreach ($this->_paymentProcessors as $id => $val) {
+                if (!$val['is_recur']) {
+                  $allowAutoRenewOpt = 0;
+                  continue;
+                }
+              }
+            }
+
+            $javascriptMethod = array('onclick' => "return showHideAutoRenew( this.value );");
+            $autoRenewMembershipTypeOptions["autoRenewMembershipType_{$value}"] = (int) $allowAutoRenewOpt * CRM_Utils_Array::value($value, CRM_Utils_Array::value('auto_renew', $this->_membershipBlock));;
+
+            if ($allowAutoRenewOpt) {
+              $allowAutoRenewMembership = TRUE;
+            }
+
+            //add membership type.
+            $radio[$memType['id']] = $this->createElement('radio', NULL, NULL, NULL,
+              $memType['id'], $javascriptMethod
+            );
+            if ($cid) {
+              $membership = new CRM_Member_DAO_Membership();
+              $membership->contact_id = $cid;
+              $membership->membership_type_id = $memType['id'];
+
+              //show current membership, skip pending and cancelled membership records,
+              //because we take first membership record id for renewal
+              $membership->whereAdd('status_id != 5 AND status_id !=6');
+
+              if (!is_null($isTest)) {
+                $membership->is_test = $isTest;
+              }
+
+              //CRM-4297
+              $membership->orderBy('end_date DESC');
+
+              if ($membership->find(TRUE)) {
+                if (!$membership->end_date) {
+                  unset($radio[$memType['id']]);
+                  $this->assign('islifetime', TRUE);
+                  continue;
+                }
+                $this->assign('renewal_mode', TRUE);
+                $this->_currentMemberships[$membership->membership_type_id] = $membership->membership_type_id;
+                $memType['current_membership'] = $membership->end_date;
+                if (!$endDate) {
+                  $endDate = $memType['current_membership'];
+                  $this->_defaultMemTypeId = $memType['id'];
+                }
+                if ($memType['current_membership'] < $endDate) {
+                  $endDate = $memType['current_membership'];
+                  $this->_defaultMemTypeId = $memType['id'];
+                }
+              }
+            }
+            $membershipTypes[] = $memType;
+          }
+        }
+      }
+
+      $this->assign('membershipBlock', $this->_membershipBlock);
+      $this->assign('showRadio', $isContributionMainPage);
+      $this->assign('membershipTypes', $membershipTypes);
+      $this->assign('allowAutoRenewMembership', $allowAutoRenewMembership);
+      $this->assign('autoRenewMembershipTypeOptions', json_encode($autoRenewMembershipTypeOptions));
+      //give preference to user submitted auto_renew value.
+      $takeUserSubmittedAutoRenew = (!empty($_POST) || $this->isSubmitted()) ? TRUE : FALSE;
+      $this->assign('takeUserSubmittedAutoRenew', $takeUserSubmittedAutoRenew);
+
+      if ($isContributionMainPage) {
+        if (!$membershipPriceset) {
+          if (!$this->_membershipBlock['is_required']) {
+            $this->assign('showRadioNoThanks', TRUE);
+            $radio[''] = $this->createElement('radio', NULL, NULL, NULL, 'no_thanks', NULL);
+            $this->addGroup($radio, 'selectMembership', NULL);
+          }
+          elseif ($this->_membershipBlock['is_required'] && count($radio) == 1) {
+            $temp = array_keys($radio);
+            $this->add('hidden', 'selectMembership', $temp[0], array('id' => 'selectMembership'));
+            $this->assign('singleMembership', TRUE);
+            $this->assign('showRadio', FALSE);
+          }
+          else {
+            $this->addGroup($radio, 'selectMembership', NULL);
+          }
+
+          $this->addRule('selectMembership', ts('Please select one of the memberships.'), 'required');
+        }
+        else {
+          $autoRenewOption = CRM_Price_BAO_PriceSet::checkAutoRenewForPriceSet($this->_priceSetId);
+          $this->assign('autoRenewOption', $autoRenewOption);
+        }
+
+        if (!$this->_values['is_pay_later'] && is_array($this->_paymentProcessors) && ($allowAutoRenewMembership || $autoRenewOption)) {
+          $this->addElement('checkbox', 'auto_renew', ts('Please renew my membership automatically.'));
+        }
+
+      }
+    }
+
+    return $separateMembershipPayment;
+  }
+
 }