Core Bugs and Webtest fixes in 4.7beta1
[civicrm-core.git] / CRM / Contribute / Form / Contribution / Main.php
index 0832bd9aa47fd006f5fe563461b8d33121ba78f9..81995735bdcf718dba445511e29c9e99768eb5dd 100644 (file)
@@ -41,10 +41,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
    */
   public $_defaultMemTypeId;
 
-  public $_relatedOrganizationFound;
-
-  public $_onBehalfRequired = FALSE;
-  public $_onbehalf = FALSE;
   public $_paymentProcessors;
 
   public $_membershipTypeValues;
@@ -78,38 +74,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $this->assign('mainDisplay', CRM_Utils_Request::retrieve('_qf_Main_display', 'Boolean',
       CRM_Core_DAO::$_nullObject));
 
-    // Possible values for 'is_for_organization':
-    // * 0 - org profile disabled
-    // * 1 - org profile optional
-    // * 2 - org profile required
-    $this->_onbehalf = FALSE;
-    if (!empty($this->_values['is_for_organization'])) {
-      if ($this->_values['is_for_organization'] == 2) {
-        $this->_onBehalfRequired = TRUE;
-      }
-      // Add organization profile if 1 of the following are true:
-      // If the org profile is required
-      if ($this->_onBehalfRequired ||
-        // Or we are building the form for the first time
-        empty($_POST) ||
-        // Or the user has submitted the form and checked the "On Behalf" checkbox
-        !empty($_POST['is_for_organization'])
-      ) {
-        $this->_onbehalf = TRUE;
-        CRM_Contribute_Form_Contribution_OnBehalfOf::preProcess($this);
-      }
-    }
-    $this->assign('onBehalfRequired', $this->_onBehalfRequired);
-
-    if ($this->_honor_block_is_active) {
-      CRM_Contact_Form_ProfileContact::preprocess($this);
-    }
-
-    if ($this->_snippet) {
-      $this->assign('isOnBehalfCallback', CRM_Utils_Array::value('onbehalf', $_GET, FALSE));
-      return;
-    }
-
     if (!empty($this->_pcpInfo['id']) && !empty($this->_pcpInfo['intro_text'])) {
       $this->assign('intro_text', $this->_pcpInfo['intro_text']);
     }
@@ -126,54 +90,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     if (!empty($this->_values['footer_text'])) {
       $this->assign('footer_text', $this->_values['footer_text']);
     }
-
-    //CRM-5001
-    //CRM-15787
-    $member = CRM_Member_BAO_Membership::getMembershipBlock($this->_id);
-    if (!empty($this->_values['is_for_organization']) && empty($member['is_active'])) {
-      $msg = ts('Mixed profile not allowed for on behalf of registration/sign up.');
-      $ufJoinParams = array(
-        'module' => 'onBehalf',
-        'entity_table' => 'civicrm_contribution_page',
-        'entity_id' => $this->_id,
-      );
-      $onBehalfProfileIDs = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams);
-      // getUFGroupIDs returns an array with the first item being the ID we need
-      $onBehalfProfileID = $onBehalfProfileIDs[0];
-      if ($onBehalfProfileID) {
-        $onBehalfProfile = CRM_Core_BAO_UFGroup::profileGroups($onBehalfProfileID);
-        foreach (array(
-                   'Individual',
-                   'Organization',
-                   'Household',
-                 ) as $contactType) {
-          if (in_array($contactType, $onBehalfProfile) &&
-            (in_array('Membership', $onBehalfProfile) ||
-              in_array('Contribution', $onBehalfProfile)
-            )
-          ) {
-            CRM_Core_Error::fatal($msg);
-          }
-        }
-      }
-
-      if ($postID = CRM_Utils_Array::value('custom_post_id', $this->_values)) {
-        $postProfile = CRM_Core_BAO_UFGroup::profileGroups($postID);
-        foreach (array(
-                   'Individual',
-                   'Organization',
-                   'Household',
-                 ) as $contactType) {
-          if (in_array($contactType, $postProfile) &&
-            (in_array('Membership', $postProfile) ||
-              in_array('Contribution', $postProfile)
-            )
-          ) {
-            CRM_Core_Error::fatal($msg);
-          }
-        }
-      }
-    }
   }
 
   /**
@@ -212,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
      *
@@ -266,7 +163,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
         }
       }
 
-      if ($this->_honor_block_is_active && count($completedContributionIds)) {
+      if (count($completedContributionIds)) {
         $softCredit = array();
         foreach ($completedContributionIds as $id) {
           $softCredit = CRM_Contribute_BAO_ContributionSoft::getSoftContribution($id);
@@ -307,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();
@@ -328,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 &&
@@ -337,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'])) {
@@ -366,6 +285,8 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $this->buildCustom($this->_values['custom_pre_id'], 'customPre');
     $this->buildCustom($this->_values['custom_post_id'], 'customPost');
 
+    $this->buildComponentForm($this->_id, $this);
+
     if (!empty($this->_fields) && !empty($this->_values['custom_pre_id'])) {
       $profileAddressFields = array();
       foreach ($this->_fields as $key => $value) {
@@ -375,9 +296,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     }
 
     // Build payment processor form
-    if (empty($_GET['onbehalf'])) {
-      CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
-    }
+    CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
 
     $config = CRM_Core_Config::singleton();
 
@@ -387,14 +306,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $this->assign('display_name', CRM_Contact_BAO_Contact::displayName($contactID));
     }
 
-    if ($this->_onbehalf) {
-      CRM_Contribute_Form_Contribution_OnBehalfOf::buildQuickForm($this);
-      // Return if we are in an ajax callback
-      if ($this->_snippet) {
-        return;
-      }
-    }
-
     $this->applyFilter('__ALL__', 'trim');
     $this->add('text', "email-{$this->_bltID}",
       ts('Email Address'),
@@ -487,25 +398,11 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       }
     }
 
-    if ($this->_values['is_for_organization']) {
-      $this->buildOnBehalfOrganization();
-    }
-
     //we allow premium for pledge during pledge creation only.
     if (empty($this->_values['pledge_id'])) {
       CRM_Contribute_BAO_Premium::buildPremiumBlock($this, $this->_id, TRUE);
     }
 
-    //add honor block
-    if ($this->_honor_block_is_active) {
-      $this->assign('honor_block_is_active', TRUE);
-
-      //build soft-credit section
-      CRM_Contribute_Form_SoftCredit::buildQuickForm($this);
-      //build honoree profile section
-      CRM_Contact_Form_ProfileContact::buildQuickForm($this);
-    }
-
     //don't build pledge block when mid is passed
     if (!$this->_mid) {
       $config = CRM_Core_Config::singleton();
@@ -572,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
@@ -609,26 +509,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $this->addFormRule(array('CRM_Contribute_Form_Contribution_Main', 'formRule'), $this);
   }
 
-  /**
-   * Build elements to enable pay on behalf of an organization.
-   */
-  public function buildOnBehalfOrganization() {
-    if ($this->_membershipContactID) {
-      $entityBlock = array('contact_id' => $this->_membershipContactID);
-      CRM_Core_BAO_Location::getValues($entityBlock, $this->_defaults);
-    }
-
-    if (!$this->_onBehalfRequired) {
-      $this->addElement('checkbox', 'is_for_organization',
-        $this->_values['for_organization'],
-        NULL, array('onclick' => "showOnBehalf( );")
-      );
-    }
-
-    $this->assign('is_for_organization', TRUE);
-    $this->assign('urlPath', 'civicrm/contribute/transact');
-  }
-
   /**
    * Build elements to collect information for recurring contributions.
    *
@@ -724,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();
 
@@ -957,29 +838,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       $errors['_qf_default'] = ts('You cannot set up a recurring contribution if you are not paying online by credit card.');
     }
 
-    if (!empty($fields['is_for_organization']) &&
-      !property_exists($self, 'organizationName')
-    ) {
-
-      if (empty($fields['onbehalf']['organization_name'])) {
-        if (!empty($fields['org_option']) && !$fields['onbehalfof_id']) {
-          $errors['organization_id'] = ts('Please select an organization or enter a new one.');
-        }
-        elseif (empty($fields['org_option'])) {
-          $errors['onbehalf']['organization_name'] = ts('Please enter the organization name.');
-        }
-      }
-
-      foreach ($fields['onbehalf'] as $key => $value) {
-        if (strstr($key, 'email')) {
-          $emailLocType = explode('-', $key);
-        }
-      }
-      if (empty($fields['onbehalf']["email-{$emailLocType[1]}"])) {
-        $errors['onbehalf']["email-{$emailLocType[1]}"] = ts('Organization email is required.');
-      }
-    }
-
     // validate PCP fields - if not anonymous, we need a nick name value
     if ($self->_pcpId && !empty($fields['pcp_display_in_roll']) &&
       (CRM_Utils_Array::value('pcp_is_anonymous', $fields) == 0) &&
@@ -1039,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)) {
@@ -1098,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]);
         }
@@ -1110,23 +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'];
     }
 
-    if (!empty($params['onbehalfof_id'])) {
-      $params['organization_id'] = $params['onbehalfof_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');
@@ -1170,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;
     }
@@ -1178,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);
@@ -1192,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;
@@ -1293,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
@@ -1315,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();
-    }
-
   }
 
   /**
@@ -1371,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);
+  }
+
 }