CRM-17500 fix display name etc not being updated from billing
authoreileen <emcnaughton@wikimedia.org>
Thu, 5 Nov 2015 05:55:03 +0000 (21:55 -0800)
committereileen <emcnaughton@wikimedia.org>
Fri, 6 Nov 2015 02:29:40 +0000 (18:29 -0800)
This is tested here in contribution flow

CRM/Contact/BAO/Contact.php
CRM/Contribute/Form/Contribution/Confirm.php
tests/phpunit/api/v3/ContributionPageTest.php

index d3a3d443ae55d65f2bce80b48effc59a76da4ddb..7bef11045bd2adf0d8d2db0c1aaa1705a29020f6 100644 (file)
@@ -523,6 +523,35 @@ WHERE     civicrm_contact.id = " . CRM_Utils_Type::escape($id, 'Integer');
     return NULL;
   }
 
+  /**
+   * Add billing fields to the params if appropriate.
+   *
+   * If we have ANY name fields then we want to ignore all the billing name fields. However, if we
+   * don't then we should set the name fields to the filling fields AND add the preserveDBName
+   * parameter (which will tell the BAO only to set those fields if none already exist.
+   *
+   * We specifically don't want to set first name from billing and last name form an on-page field. Mixing &
+   * matching is best done by hipsters.
+   *
+   * @param array $params
+   */
+  public static function addBillingNameFieldsIfOtherwiseNotSet(&$params) {
+    $nameFields = array('first_name', 'middle_name', 'last_name');
+    foreach ($nameFields as $field) {
+      if (!empty($params[$field])) {
+        return;
+      }
+    }
+    // There are only 3 - we can iterate through them twice :-)
+    foreach ($nameFields as $field) {
+      if (!empty($params['billing_' . $field])) {
+        $params[$field] = $params['billing_' . $field];
+      }
+      $params['preserveDBName'] = TRUE;
+    }
+
+  }
+
   /**
    * Create last viewed link to recently updated contact.
    *
@@ -1825,6 +1854,7 @@ ORDER BY civicrm_email.is_primary DESC";
     if ($ufGroupId) {
       $params['uf_group_id'] = $ufGroupId;
     }
+    self::addBillingNameFieldsIfOtherwiseNotSet($params);
 
     // If a user has logged in, or accessed via a checksum
     // Then deliberately 'blanking' a value in the profile should remove it from their record
@@ -2018,7 +2048,7 @@ ORDER BY civicrm_email.is_primary DESC";
     $primaryPhoneLoc = NULL;
     $session = CRM_Core_Session::singleton();
     foreach ($params as $key => $value) {
-      $fieldName = $locTypeId = $typeId = NULL;
+      $locTypeId = $typeId = NULL;
       list($fieldName, $locTypeId, $typeId) = CRM_Utils_System::explode('-', $key, 3);
 
       //store original location type id
index e0a9f952798b4c18502d41e4e6e2610daa61107d..c7d87c83ab095aa931767e2a45c58d675c2ea98d 100644 (file)
@@ -1825,6 +1825,9 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     $params['invoiceID'] = md5(uniqid(rand(), TRUE));
     $paramsProcessedForForm = $form->_params = self::getFormParams($params['id'], $params);
     $form->_amount = $params['amount'];
+    // hack these in for test support.
+    $form->_fields['billing_first_name'] = 1;
+    $form->_fields['billing_last_name'] = 1;
     $priceSetID = $form->_params['priceSetId'] = $paramsProcessedForForm['price_set_id'];
     $priceFields = CRM_Price_BAO_PriceSet::getSetDetail($priceSetID);
     $priceSetFields = reset($priceFields);
@@ -1933,31 +1936,6 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     // billing email address
     $fields["email-{$this->_bltID}"] = 1;
 
-    //unset the billing parameters if it is pay later mode
-    //to avoid creation of billing location
-    // @todo - note that elsewhere we don't unset these - we simply make
-    // a sensible decision about including them when building the form
-    // and if they are submitted we handle them. Check out abstractEditPaymentForm.
-    if ($isPayLater && !$this->_isBillingAddressRequiredForPayLater) {
-      $billingFields = array(
-        'billing_first_name',
-        'billing_middle_name',
-        'billing_last_name',
-        "billing_street_address-{$this->_bltID}",
-        "billing_city-{$this->_bltID}",
-        "billing_state_province-{$this->_bltID}",
-        "billing_state_province_id-{$this->_bltID}",
-        "billing_postal_code-{$this->_bltID}",
-        "billing_country-{$this->_bltID}",
-        "billing_country_id-{$this->_bltID}",
-      );
-
-      foreach ($billingFields as $value) {
-        unset($params[$value]);
-        unset($fields[$value]);
-      }
-    }
-
     // if onbehalf-of-organization contribution, take out
     // organization params in a separate variable, to make sure
     // normal behavior is continued. And use that variable to
index 1a46c1f6319a62a93a4a91e2db3fbb85f7962e48..de6cb22d06dcb2889f82df9b7c6357cc21dd6445 100644 (file)
@@ -149,6 +149,91 @@ class api_v3_ContributionPageTest extends CiviUnitTestCase {
     $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
   }
 
+  /**
+   * Test form submission with billing first & last name where the contact does NOT
+   * otherwise have one.
+   */
+  public function testSubmitNewBillingNameData() {
+    $this->setUpContributionPage();
+    $contact = $this->callAPISuccess('Contact', 'create', array('contact_type' => 'Individual', 'email' => 'wonderwoman@amazon.com'));
+    $priceFieldID = reset($this->_ids['price_field']);
+    $priceFieldValueID = reset($this->_ids['price_field_value']);
+    $submitParams = array(
+      'price_' . $priceFieldID => $priceFieldValueID,
+      'id' => (int) $this->_ids['contribution_page'],
+      'amount' => 10,
+      'billing_first_name' => 'Wonder',
+      'billing_last_name' => 'Woman',
+      'contactID' => $contact['id'],
+      'email' => 'wonderwoman@amazon.com',
+    );
+
+    $this->callAPISuccess('contribution_page', 'submit', $submitParams);
+    $contact = $this->callAPISuccess('Contact', 'get', array(
+      'id' => $contact['id'],
+      'return' => array(
+        'first_name',
+        'last_name',
+        'sort_name',
+        'display_name',
+      ),
+    ));
+    $this->assertEquals(array(
+      'first_name' => 'Wonder',
+      'last_name' => 'Woman',
+      'display_name' => 'Wonder Woman',
+      'sort_name' => 'Woman, Wonder',
+      'id' => $contact['id'],
+      'contact_id' => $contact['id'],
+    ), $contact['values'][$contact['id']]);
+
+  }
+
+  /**
+   * Test form submission with billing first & last name where the contact does
+   * otherwise have one and should not be overwritten.
+   */
+  public function testSubmitNewBillingNameDoNotOverwrite() {
+    $this->setUpContributionPage();
+    $contact = $this->callAPISuccess('Contact', 'create', array(
+      'contact_type' => 'Individual',
+      'email' => 'wonderwoman@amazon.com',
+      'first_name' => 'Super',
+      'last_name' => 'Boy',
+    ));
+    $priceFieldID = reset($this->_ids['price_field']);
+    $priceFieldValueID = reset($this->_ids['price_field_value']);
+    $submitParams = array(
+      'price_' . $priceFieldID => $priceFieldValueID,
+      'id' => (int) $this->_ids['contribution_page'],
+      'amount' => 10,
+      'billing_first_name' => 'Wonder',
+      'billing_last_name' => 'Woman',
+      'contactID' => $contact['id'],
+      'email' => 'wonderwoman@amazon.com',
+    );
+
+    $this->callAPISuccess('contribution_page', 'submit', $submitParams);
+    $contact = $this->callAPISuccess('Contact', 'get', array(
+      'id' => $contact['id'],
+      'return' => array(
+        'first_name',
+        'last_name',
+        'sort_name',
+        'display_name',
+      ),
+    ));
+    $this->assertEquals(array(
+      'first_name' => 'Super',
+      'last_name' => 'Boy',
+      'display_name' => 'Super Boy',
+      'sort_name' => 'Boy, Super',
+      'id' => $contact['id'],
+      'contact_id' => $contact['id'],
+    ), $contact['values'][$contact['id']]);
+
+  }
+
   /**
    * Test process with instant payment when more than one configured for the page.
    *