Core Bugs and Webtest fixes in 4.7beta1
[civicrm-core.git] / CRM / Contribute / Form / Contribution / Main.php
index ca53823def8fa42ce966871a677ec6fa39a7b006..81995735bdcf718dba445511e29c9e99768eb5dd 100644 (file)
@@ -128,25 +128,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $this->_defaults = array_merge($this->_defaults, $billingDefaults);
     }
 
-    //set custom field defaults set by admin if value is not set
-    if (!empty($this->_fields)) {
-      //load default campaign from page.
-      if (array_key_exists('contribution_campaign_id', $this->_fields)) {
-        $this->_defaults['contribution_campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values);
-      }
-
-      //set custom field defaults
-      foreach ($this->_fields as $name => $field) {
-        if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) {
-          if (!isset($this->_defaults[$name])) {
-            CRM_Core_BAO_CustomField::setProfileDefaults($customFieldID, $name, $this->_defaults,
-              NULL, CRM_Profile_Form::MODE_REGISTER
-            );
-          }
-        }
-      }
-    }
-
     /*
      * hack to simplify credit card entry for testing
      *
@@ -223,6 +204,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $this->_defaults["billing_state_province_id-{$this->_bltID}"] = $config->defaultContactStateProvince;
     }
 
+    $entityId = $memtypeID = NULL;
     if ($this->_priceSetId) {
       if (($this->_useForMember && !empty($this->_currentMemberships)) || $this->_defaultMemTypeId) {
         $selectedCurrentMemTypes = array();
@@ -244,7 +226,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
               !in_array($opMemTypeId, $selectedCurrentMemTypes)
             ) {
               CRM_Price_BAO_PriceSet::setDefaultPriceSetField($priceFieldName, $keys, $val['html_type'], $this->_defaults);
-              $selectedCurrentMemTypes[] = $values['membership_type_id'];
+              $memtypeID = $selectedCurrentMemTypes[] = $values['membership_type_id'];
             }
             elseif (!empty($values['is_default']) &&
               !$opMemTypeId &&
@@ -253,15 +235,36 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
                 !isset($this->_defaults[$priceFieldName][$keys]))
               )) {
                 CRM_Price_BAO_PriceSet::setDefaultPriceSetField($priceFieldName, $keys, $val['html_type'], $this->_defaults);
+                $memtypeID = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $this->_defaults[$priceFieldName], 'membership_type_id');
             }
           }
         }
+        $entityId = CRM_Utils_Array::value('id', CRM_Member_BAO_Membership::getContactMembership($contactID, $memtypeID, NULL));
       }
       else {
         CRM_Price_BAO_PriceSet::setDefaultPriceSet($this, $this->_defaults);
       }
     }
 
+    //set custom field defaults set by admin if value is not set
+    if (!empty($this->_fields)) {
+      //load default campaign from page.
+      if (array_key_exists('contribution_campaign_id', $this->_fields)) {
+        $this->_defaults['contribution_campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values);
+      }
+
+      //set custom field defaults
+      foreach ($this->_fields as $name => $field) {
+        if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) {
+          if (!isset($this->_defaults[$name])) {
+            CRM_Core_BAO_CustomField::setProfileDefaults($customFieldID, $name, $this->_defaults,
+              $entityId, CRM_Profile_Form::MODE_REGISTER
+            );
+          }
+        }
+      }
+    }
+
     if (!empty($this->_paymentProcessors)) {
       foreach ($this->_paymentProcessors as $pid => $value) {
         if (!empty($value['is_default'])) {
@@ -466,6 +469,9 @@ 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'])) {
+      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.'));
+    }
 
     //we have to load confirm contribution button in template
     //when multiple payment processor as the user
@@ -598,7 +604,8 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         $self->_useForMember
       )
     ) {
-      $lifeMember = CRM_Member_BAO_Membership::getAllContactMembership($self->_membershipContactID, FALSE, TRUE);
+      $isTest = ($self->_action & CRM_Core_Action::PREVIEW) ? TRUE : FALSE;
+      $lifeMember = CRM_Member_BAO_Membership::getAllContactMembership($self->_membershipContactID, $isTest, TRUE);
 
       $membershipOrgDetails = CRM_Member_BAO_MembershipType::getMembershipTypeOrganization();
 
@@ -890,22 +897,18 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       }
     }
 
-    // also return if paylater mode
-    if (CRM_Utils_Array::value('payment_processor_id', $fields) == 0 && $self->_isBillingAddressRequiredForPayLater == 0) {
-      return empty($errors) ? TRUE : $errors;
-    }
-
     // if the user has chosen a free membership or the amount is less than zero
-    // i.e. we skip calling the payment processor and hence dont need credit card
-    // info
+    // i.e. we don't need to validate payment related fields or profiles.
     if ((float) $amount <= 0.0) {
       return $errors;
     }
 
-    if (!empty($self->_paymentFields)) {
-      CRM_Core_Form::validateMandatoryFields($self->_paymentFields, $fields, $errors);
-    }
-    CRM_Core_Payment_Form::validatePaymentInstrument($fields['payment_processor_id'], $fields, $errors, $self);
+    CRM_Core_Payment_Form::validatePaymentInstrument(
+      $fields['payment_processor_id'],
+      $fields,
+      $errors,
+      (!$self->_isBillingAddressRequiredForPayLater ? NULL : 'billing')
+    );
 
     foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
       if ($greetingType = CRM_Utils_Array::value($greeting, $fields)) {
@@ -949,6 +952,10 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         $amountID = CRM_Utils_Array::value('amount', $params);
 
         if ($amountID) {
+          // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel
+          // function to get correct amount level consistently. Remove setting of the amount level in
+          // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest
+          // to cover all variants.
           $params['amount_level'] = CRM_Utils_Array::value('label', $formValues[$amountID]);
           $amount = CRM_Utils_Array::value('value', $formValues[$amountID]);
         }
@@ -961,19 +968,34 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
    * Process the form submission.
    */
   public function postProcess() {
-    $config = CRM_Core_Config::singleton();
     // we first reset the confirm page so it accepts new values
     $this->controller->resetPage('Confirm');
 
     // get the submitted form values.
     $params = $this->controller->exportValues($this->_name);
+    $this->submit($params);
 
+    if (empty($this->_values['is_confirm_enabled'])) {
+      $this->skipToThankYouPage();
+    }
+
+  }
+
+  /**
+   * Submit function.
+   *
+   * This is the guts of the postProcess made also accessible to the test suite.
+   *
+   * @param array $params
+   *   Submitted values.
+   */
+  public function submit($params) {
     //carry campaign from profile.
     if (array_key_exists('contribution_campaign_id', $params)) {
       $params['campaign_id'] = $params['contribution_campaign_id'];
     }
 
-    $params['currencyID'] = $config->defaultCurrency;
+    $params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency;
 
     if (!empty($params['priceSetId'])) {
       $is_quick_config = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config');
@@ -1017,7 +1039,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     if (($this->_values['is_pay_later'] &&
         empty($this->_paymentProcessor) &&
         !array_key_exists('hidden_processor', $params)) ||
-      (!empty($params['payment_processor_id']) && $params['payment_processor_id'] == 0)
+      (CRM_Utils_Array::value('payment_processor_id', $params) == 0)
     ) {
       $params['is_pay_later'] = 1;
     }
@@ -1025,6 +1047,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $params['is_pay_later'] = 0;
     }
 
+    // Would be nice to someday understand the point of this set.
     $this->set('is_pay_later', $params['is_pay_later']);
     // assign pay later stuff
     $this->_params['is_pay_later'] = CRM_Utils_Array::value('is_pay_later', $params, FALSE);
@@ -1039,14 +1062,12 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $params['separate_amount'] = $params['amount'];
     $memFee = NULL;
     if (!empty($params['selectMembership'])) {
-      if (!empty($this->_membershipTypeValues)) {
-        $membershipTypeValues = $this->_membershipTypeValues[$params['selectMembership']];
-      }
-      else {
-        $membershipTypeValues = CRM_Member_BAO_Membership::buildMembershipTypeValues($this,
+      if (empty($this->_membershipTypeValues)) {
+        $this->_membershipTypeValues = CRM_Member_BAO_Membership::buildMembershipTypeValues($this,
           (array) $params['selectMembership']
         );
       }
+      $membershipTypeValues = $this->_membershipTypeValues[$params['selectMembership']];
       $memFee = $membershipTypeValues['minimum_fee'];
       if (!$params['amount'] && !$this->_separateMembershipPayment) {
         $params['amount'] = $memFee ? $memFee : 0;
@@ -1140,13 +1161,17 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $invoiceID = md5(uniqid(rand(), TRUE));
     $this->set('invoiceID', $invoiceID);
     $params['invoiceID'] = $invoiceID;
-    $params['description'] = ts('Online Contribution') . ': ' . (($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']);
+    $params['description'] = ts('Online Contribution') . ': ' . ((!empty($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']));
     $params['button'] = $this->controller->getButtonName();
     // required only if is_monetary and valid positive amount
+    // @todo it seems impossible for $memFee to be greater than 0 & $params['amount'] not to
+    // be & by requiring $memFee down here we make it harder to do a sensible refactoring of the function
+    // above (ie. extract the amount in a small function).
     if ($this->_values['is_monetary'] &&
-      is_array($this->_paymentProcessor) &&
+      !empty($this->_paymentProcessor) &&
       ((float ) $params['amount'] > 0.0 || $memFee > 0.0)
     ) {
+      // The concept of contributeMode is deprecated - as should be the 'is_monetary' setting.
       $this->setContributeMode();
       // Really this setting of $this->_params & params within it should be done earlier on in the function
       // probably the values determined here should be reused in confirm postProcess as there is no opportunity to alter anything
@@ -1162,11 +1187,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         $this->handlePreApproval($this->_params);
       }
     }
-
-    if (empty($this->_values['is_confirm_enabled'])) {
-      $this->skipToThankYouPage();
-    }
-
   }
 
   /**
@@ -1218,4 +1238,15 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact', "_qf_ThankYou_display=1&qfKey=$qfKey", TRUE, NULL, FALSE));
   }
 
+  /**
+   * Function for unit tests on the postProcess function.
+   *
+   * @param array $params
+   */
+  public function testSubmit($params) {
+    $_SERVER['REQUEST_METHOD'] = 'GET';
+    $this->controller = new CRM_Contribute_Controller_Contribution();
+    $this->submit($params);
+  }
+
 }